Menu

#327 Update mac os implementation to use launchctl bootout bootstrap

v3.6.3
open
nobody
None
5
2025-10-17
2025-09-25
No

launchctl's load and unload commands are considered legacy at this point and swapping to bootout and bootstrap should be fairly trivial.

instead of:

launchctl unload "/Library/LaunchDaemons/${APP_PLIST}"
launchctl load "/Library/LaunchDaemons/${APP_PLIST}"

it becomes

launchctl bootout "system/${APP_PLIST_BASE}"
launchctl bootstrap system "/Library/LaunchDaemons/${APP_PLIST}"

also, while we are in here we should alter the macosRestart() function to actually wait for the process to be stopped instead of a hardcoded sleep 1 like so:

macosxRestart() {
    mustBeRootOrExit
    checkRunning $1

    eval echo `gettext 'Restarting $APP_LONG_NAME...'`

    if [ "$MACOSX_KEEP_RUNNING" = "true" ] ; then
        # by stopping it, launchd will automatically restart it
        launchctl stop ${APP_PLIST_BASE}
    else
        launchctl bootout "system/${APP_PLIST_BASE}"
        timeout=60
        while [ $timeout -gt 0 ] && pgrep -f "$PIDFILE" > /dev/null; do
            sleep 1
            ((timeout--))
        done
        launchctl bootstrap system "/Library/LaunchDaemons/${APP_PLIST}"
    fi

    startwait
}

Discussion

  • Maxime Andrighetto

    Hi Jonathan,

    Thank you very much for bringing this issue to our attention.

    I believe 'launchctl bootout/bootstrap' was introduced in macOS 10.10 Yosemite. The current Wrapper still supports older macOS versions, so we need to maintain compatibility for now. But we plan to raise the system requirements in the next release (3.7.0), which will allow us to implement macosxRestart() as you've suggested.

    When restarting the Wrapper, we typically call waitForWrapperStop() in the shell script, which uses a loop similar to your proposed code. We could also introduce a timeout as you suggested.

    We will update this thread once this change is implemented.

    Thank you again for your suggestion.

    Best regards,

    Maxime Andrighetto

     
  • Maxime Andrighetto

    Hi Jonathan,

    Thank you again for your contribution.

    We have implemented changes similar to your suggestions.

    However, we found that instead of waiting for process termination, it is more reliable to wait for the service to be unbooted by launchd.
    launchd normally sends a TERM signal to the process and unloads it upon confirmation of termination, but there can be a slight delay between the process stopping and the service actually being unloaded.
    Attempting to execute launchctl bootstrap might result in an error like the following:

    service already bootstrapped
    Bootstrap failed: 37: Operation already in progress
    

    The fix will be available in the next Wrapper release.

    Best Regards,

    Maxime

     

Log in to post a comment.