2
votes

I have a application run as a daemon. I put the application plist under under /Library/LaunchDaemons on iOS 8 device, and launch it by executing the command

launchctl load /Library/LaunchDaemons/com.mycompany.testapp.plist

In my laumchd plist Note that the application is running as a daemon by executing the command

I would like to make this application restart only when it is crash or is killed. If I intentionally exit it with code 0, I don't want it to restart. I've tried the below configuration. This does work on iOS 7, but do NOT work on iOS 8.

<key>KeepAlive</key>
<dict>
    <key>SuccessfulExit</key>
    <true/>
</dict>

Thus I tried adding another key StartInterval which's set as 10.

<key>StartInterval</key>
<integer>10</integer>

I tested this scenario by exit with code 0 and by kill my application with command kill -9 [PID]. This key makes my application to start again after 10 seconds after being killled. However, I have a concern about the result of this key while my application is running.

Does this key have an affect on the started and running application. I've monitored the log, seem StartInterval key do nothing with the running daemon. However, I'm quite not sure about it. Could you explain more information about it? Thank you very much.

2

2 Answers

1
votes

According to this link http://pitaya.ch/documentation/iOS8_0APIDiffs.html all traces to launchd in the headers have disappeared. (search for /usr/include/launch.h, so you see it was removed) Seems because the moved to new libxpc as base for launchd (see last slide in http://technologeeks.com/docs/launchd.pdf).

Seems like they changed launchd behaviour in iOS 8. Of Apple's own LaunchDaemons (located under /System/Library/LaunchDaemons/) some also have a KeepAlive-property in Dictionary format. If you kill them, they are respawned by launchd instantly.

But after some testing the only way to have KeepAlive-property working, is to add either add LaunchEvents (see slide 21ff in http://technologeeks.com/docs/launchd.pdf) and/or MachServices to the plist or to change the KeepAlive-property to:

<key>KeepAlive</key>
<true/>

But then there is NO way to kill your deamon without launchd respawning it, aside from executing launchctl unload /Library/LaunchDaemons/com.mycompany.testapp.plist.

My working plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Program</key>
    <string>/path/to/your/daemon</string>
    <key>RunAtLoad</key>
    <true/>
    <key>Label</key>
    <string>com.mycompany.testapp</string>
    <key>EnablePressuredExit</key>
    <false/>
    <key>UserName</key>
    <string>root</string>
    <key>JetsamProperties</key>
    <dict>
        <key>JetsamPriority</key>
        <integer>-49</integer>
        <key>JetsamMemoryLimit</key>
        <integer>10000</integer>
    </dict>
    <key>POSIXSpawnType</key>
    <string>Adaptive</string>
    <key>Disabled</key>
    <false/>
    <key>ThrottleInterval</key>
    <integer>5</integer>
    <key>KeepAlive</key>
    <dict>
        <key>SuccessfulExit</key>
        <false/>
        <key>Crashed</key>
        <true/>
    </dict>
    <key>MachServices</key>
    <dict>
        <key> com.mycompany.testapp.someMachService</key>
        <true/>
    </dict>
    <key>EnableTransactions</key>
    <false/>
    <key>LaunchEvents</key>
    <dict>
        <key>com.apple.notifyd.matching</key>
        <dict>
            <key>SignificantTimeChangeNotification</key>
            <dict>
                <key>Notification</key>
                <string>SignificantTimeChangeNotification</string>
            </dict>
            <key>SomeMoreNotifications</key>
            [...]
        </dict>
    </dict>
</dict>
</plist>

About the StartInterval-property: Even Apple has this property in addition to the KeepAlive-property for some important daemons (e.g. com.apple.locationd) and they seem running just fine. So I don't think you have to worry...

0
votes

Use false with SuccessfulExit key.

SuccessfulExit If true, the job will be restarted as long as the program exits and with an exit status of zero. If false, the job will be restarted in the inverse condition. This key implies that "RunAtLoad" is set to true, since the job needs to run at least once before we can get an exit status.