Ahad Khan
Ahad Khan

Reputation: 411

Programmatically stop and start daemon

I want to stop my daemon from inside it. In other words daemon should stop and restart itself when a specific event occur. I am using following command it works fine in terminal but not inside daemon.

system("launchctl stop com.test.myDaemon");

Upvotes: 0

Views: 1494

Answers (2)

Nate
Nate

Reputation: 31045

creker's answer worked for me on a jailbroken iOS 7.0.4 phone. However, you should be able to make your launchctl work as well (yes, I tested this, too).

Here are some things you might want to check:

  1. Are you doing something in your daemon's plist file that changes which user it runs as? If you are telling launchd to run your daemon as a non-root user, that might prevent your programmatic launchctl command from working.

  2. Do you have an entry in your plist file for the OnDemand key? Normally, you shouldn't. I'm wondering if you do, and it's conflicting with the KeepAlive setting in creker's answer.

  3. Are you sure that this command exactly (launchctl stop com.test.myDaemon) succeeds from the command line?

The reason I ask is that many people build their Launch Daemons based on a tutorial here. In general, it's a great tutorial. But, there is at least one mistake. In the sample daemon .plist file, the value here for Label:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.chrisalvares.DLocationDemon.plist</string>

is not correct. It shouldn't be com.chrisalvares.DLocationDemon.plist. It should just be com.chrisalvares.DLocationDemon. In many cases, it doesn't matter. But, if you are issuing launchctl stop commands, the name for Label must match what you pass to launchctl. If you repeated the mistake in the tutorial, then you either need to fix the plist file, or use this command:

system("launchctl stop com.test.myDaemon.plist");

    4. Finally, there might be an issue with calling exit(0). First, it's possible that if you run this enough times, and call exit(0) enough times, iOS might flag your process as a badly behaving process, and refuse to continue to restart it. I don't think these rules are documented anywhere, but there are other similar features in iOS that work this way. So, that might suggest using launchctl instead. The other thought I had is that, even though exit(0); worked once for me, it's possible that you should chose a different exit code (not 0). I know that with VoIP apps (which are similar to a daemon in some ways), iOS only restarts your app automatically if it exits with a non-zero exit code. So, you might try exit(1);.

Those are my best guesses.

References

https://developer.apple.com/library/mac/documentation/macosx/conceptual/bpsystemstartup/chapters/CreatingLaunchdJobs.html

Upvotes: 2

creker
creker

Reputation: 9570

Probably the simplest way of doing it.

In your daemon plist file add this

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

That way iOS will automatically restart your daemon when it quits for whatever reason (signal, exception, daemon itself).

When you need to restart your daemon simply call

exit(0);

Upvotes: 3

Related Questions