3

I have a general question regarding the right way to do software updates on OS X. My application runs two daemons, both as root. One of the daemons can download the software update package from the network. When downloaded it must install the new binaries, including two binaries replacing the current ones for the daemons. Since both the daemons are currently running, replacing them might be a issue. Hence I have few ideas, however it would helpful to get expert advice on the same.

Method 1: After downloading the update, it can be kept in some location. The update daemon can place a bash script in another specified location and create a plist which can be placed in the LaunchDaemons directory to be triggered during the next reboot. The script simply replaces both the binaries before startup. This is possible only if we can ensure that the two daemons do not start up before my script executes. I didn't find a good way to tell launchd to run my script first, before starting the daemons. So I am not quite sure if this is a good solution.

Method 2: After download, immediately launch a script using launchd programatically. This should be possible, right? The script waits for a TERM signal like shown here https://discussions.apple.com/thread/3636062?start=0&tstart=0 to actually replace the binaries and exit gracefully. Again the problem is, when my script gets launched, I must be sure that my daemons are shut down before replacing the binaries. I am not sure how to do this.

Can anyone suggest which is the better approach and also let me know of any better way?

jscs
  • 63,694
  • 13
  • 151
  • 195
user2085689
  • 336
  • 3
  • 17

1 Answers1

1

The solution I use to update daemon is to launch separate shell script which do the next:

  • unload daemon via launchctl unload -w path.to.plist, it will wait for the job to finish.
  • remove old files
  • install new files (here I actually install the package, which will launch my daemon in postflight script)
  • optional: launch daemon with launchctl load -w path.to.plist

To execute script you need just fork(), setsid() and execv()

You can use applescript in your shell script to gracefully quit application:

osascript << EOF
if application "Your Application" is running then
    -- Force application to quit
    tell application "Your Application" to quit
    -- Wait until it quits
    repeat
        if application "Your Application" is not running then exit repeat
        delay 1
    end repeat
end if
EOF
killall -15 your_app # just in case
cody
  • 3,233
  • 1
  • 22
  • 25
  • What if there is a .app application that is running. How to update that? That would not have been launched by launcd? Do we kill it abruptly? Does not seem very nice to me. Also what if the user is actually using the application when the update daemon kicks in and does this? – user2085689 Apr 10 '13 at 07:38
  • I've updated my post to quit application. And you can show some notification to user, that update will be performed now. – cody Apr 10 '13 at 07:43
  • Thanks cody! Whats happens if the app for some reason refuses to closedown. We do see apps that just hang and not close down? This script will go on waiting forever? I tried it and it works well but then my app didnt hang. I tried to call the script from my app which does NOT have admin permission to just see what till happen. I used the method written here http://stackoverflow.com/questions/6841937/authorizationexecutewithprivileges-is-deprecated to run the script from program without need to fork and exec. I got the prompt but it failed with errors – user2085689 Apr 11 '13 at 00:37
  • coreservicesd[26]: Application App:"Simple Downloader" [ 0x0/0x1214213] @ 0x0x7f9304b7c000 tried to be brought forward, but isn't in fPermittedFrontASNs ( ( ASN:0x0-0x1216215:) ), so denying. – user2085689 Apr 11 '13 at 00:38
  • and finally failed after few seconds with Simple Downloader[24038]: Script execution failed! Error - 128:132: execution error: Simple Downloader got an error: AppleEvent timed out. (-1712) Is this apple script timeout? – user2085689 Apr 11 '13 at 00:39
  • For the apps that refuses to quit - you can add some sort of counter to the loop in the Apple Script and exit script if application doesn't quit. As for the errors: sorry, but I've never seen such errors before. You can try to remove cycle from script and see if there still be errors. – cody Apr 11 '13 at 05:29