Daemon & Network Availability?
Hello, all! I'm working on a project comprised of a launchd daemon and a GUI client app. I used the BetterAuthorizationSample project as a template for installing and starting up the daemon the first time. In the daemon's start-up code, it connects to a remote server. It all works fine on installation. However, when I reboot my computer, the daemon starts up, but the network isn't available yet, and the connection fails. I tried using SystemConfiguration notifications to receive changes to the network state, but that doesn't work - the computer has an IP address at that point, but the remote server is still not reachable. I also tried setting the KeepAlive option in the daemon's plist to NetworkState = true. However, that doesn't seem to work either - it just starts as KeepAlive = true. Is there some other way to indicate a dependency on the network? Do I need a delay at start up to wait for a connection? For better or worse, I used a named DO connection to handle IAC between the daemon & GUI. Could this be part of the problem (the caveats in TN2083 lead me to believe it's just inadvisable but not wrong outright)? Also, is launchd checkin, etc., required? I did have it in main(), but it kept failing, even though I had ServiceIPC = true. In case it helps, the current daemon plist is below. Thanks. ---- Karl Moskowski <kolpanic@voodooergonomics.com> Voodoo Ergonomics Inc. <http://voodooergonomics.com/> <?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>KeepAlive</key> <dict> <key>NetworkState</key> <true/> </dict> <key>Label</key> <string>com.company.myd</string> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/com.company.myd</string> </array> </dict> </plist>
Hi Karl, I have a similar implementation, I think this is what you want, as one who has been socket programming on Unix for 25 years I need to get my head around not doing my own fd plumbing, rather trusting launchd to do it for me. It also means you need to spend some time re-factoring your code. inetdCompatibility <dictionary> The presence of this key specifies that the daemon expects to be run as if it were launched from inetd. Wait <boolean> This flag corresponds to the "wait" or "nowait" option of inetd. If true, then the listening socket is passed via the standard in/out/error file descriptors. If false, then accept(2) is called on behalf of the job, and the result is passed via the standard in/out/error descriptors. On Nov 10, 2008, at 8:09 AM, Karl Moskowski wrote:
Hello, all!
I'm working on a project comprised of a launchd daemon and a GUI client app. I used the BetterAuthorizationSample project as a template for installing and starting up the daemon the first time. In the daemon's start-up code, it connects to a remote server. It all works fine on installation. However, when I reboot my computer, the daemon starts up, but the network isn't available yet, and the connection fails.
I tried using SystemConfiguration notifications to receive changes to the network state, but that doesn't work - the computer has an IP address at that point, but the remote server is still not reachable. I also tried setting the KeepAlive option in the daemon's plist to NetworkState = true. However, that doesn't seem to work either - it just starts as KeepAlive = true.
Is there some other way to indicate a dependency on the network? Do I need a delay at start up to wait for a connection? For better or worse, I used a named DO connection to handle IAC between the daemon & GUI. Could this be part of the problem (the caveats in TN2083 lead me to believe it's just inadvisable but not wrong outright)? Also, is launchd checkin, etc., required? I did have it in main(), but it kept failing, even though I had ServiceIPC = true. In case it helps, the current daemon plist is below.
Thanks.
---- Karl Moskowski <kolpanic@voodooergonomics.com> Voodoo Ergonomics Inc. <http://voodooergonomics.com/>
<?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>KeepAlive</key> <dict> <key>NetworkState</key> <true/> </dict> <key>Label</key> <string>com.company.myd</string> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/com.company.myd</string> </array> </dict> </plist>
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
On 10-Nov-08, at 12:09 PM, Ned Hogan wrote:
Hi Karl,
I have a similar implementation, I think this is what you want, as one who has been socket programming on Unix for 25 years I need to get my head around not doing my own fd plumbing, rather trusting launchd to do it for me. It also means you need to spend some time re-factoring your code.
inetdCompatibility <dictionary> The presence of this key specifies that the daemon expects to be run as if it were launched from inetd.
Wait <boolean> This flag corresponds to the "wait" or "nowait" option of inetd. If true, then the listening socket is passed via the standard in/out/error file descriptors. If false, then accept(2) is called on behalf of the job, and the result is passed via the standard in/out/error descriptors.
Thanks for the info, Ned. Would I need this if my daemon doesn't provide any networks services? (The daemon really just a client for a network service - I made it a daemon because it has to run without a user logged into Mac OS X.) What type of refactoring do you think would be required? BTW, I added the usual launchd checkin code to main(), and set ServiceIPC to true in the plist, to see if that helped out. It didn't - the launchd checkin fails with errno 13 (EACCES). I'd expect that to happen if, e.g., I ran it manually from Terminal, not if launchd started it. ---- Karl Moskowski <kolpanic@voodooergonomics.com> Voodoo Ergonomics Inc. <http://voodooergonomics.com/>
I have a couple of comments and a couple of questions... At 12:46 -0500 10/11/08, Karl Moskowski wrote:
Thanks for the info, Ned. Would I need this if my daemon doesn't provide any networks services? (The daemon really just a client for a network service - I made it a daemon because it has to run without a user logged into Mac OS X.) What type of refactoring do you think would be required?
All of the "check in with launchd" stuff is only necessary when you're vending a service and you want to launch on demand. If you're connecting to a service, you shouldn't need it. Q1: Are you planning to launch on demand, or do you want to launch at startup and keep running? A launchd daemon that's set to launch at startup will launch well before the network comes up. Keep in mind that the network may /never/ come up, or may come up and go down (repeatedly even), so it's not a case of simply waiting for the network to come up, you have to track the network state. Q2: Do you want to be running even if there's no possibility of connecting to your network service? S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware
On 11-Nov-08, at 4:28 AM, Quinn wrote:
All of the "check in with launchd" stuff is only necessary when you're vending a service and you want to launch on demand. If you're connecting to a service, you shouldn't need it.
I wasn't aware of that. I'd read things about how a daemon has to promise to checkin with launchd, etc., so I thought it was an across- the-board requirement.
Q1: Are you planning to launch on demand, or do you want to launch at startup and keep running?
A launchd daemon that's set to launch at startup will launch well before the network comes up. Keep in mind that the network may / never/ come up, or may come up and go down (repeatedly even), so it's not a case of simply waiting for the network to come up, you have to track the network state.
Q2: Do you want to be running even if there's no possibility of connecting to your network service?
I had hoped that KeepAlive={NetworkState=true} would automatically start & stop the daemon with the network being connected & disconnected. Since that seems to be incorrect, I guess I have to make it launch at startup and keep running. I can programmatically check if the network is available (using SystemConfiguration notifications, I think, unless there's a better way), and start/stop activity appropriately. ---- Karl Moskowski <kolpanic@voodooergonomics.com> Voodoo Ergonomics Inc. <http://voodooergonomics.com/>
At 9:19 -0500 11/11/08, Karl Moskowski wrote:
I had hoped that KeepAlive={NetworkState=true} would automatically start & stop the daemon with the network being connected & disconnected. Since that seems to be incorrect, I guess I have to make it launch at startup and keep running. I can programmatically check if the network is available (using SystemConfiguration notifications, I think, unless there's a better way), and start/stop activity appropriately.
"NetworkState" is a very clumsy switch. For example, it doesn't distinguish between normal IP addresses and link-local IP addresses. I suggest you use this in concert with your System Configuration framework code. That is, use "NetworkState" to allow you to completely shut down when the user has no networking then, when you are launched, use SCF to decide whether to actually try connecting or not. Earlier you wrote:
- launchd loads the daemon as soon as the network interface is available, before it has a valid IP address.
Seems unlikely to me. It may be that the interface has a valid IPv6 address (the link local one, which arrives very quickly), but not a valid IPv4 address (which typically comes from DHCP, and thus arrives very slowly). You can see the exact criteria that launchd uses to determine whether the network is up or down by looking at the get_network_state in "launchd.c". <http://www.opensource.apple.com/darwinsource/10.5.5/launchd-258.18/launchd/src/launchd.c> [This link may require an APSL <http://www.opensource.apple.com/apsl/> account.]
- launchd loads the daemon at boot if any network interfaces are connected (e.g., Parallels ports)
Does "Parallels ports" mean that that you have Parallels installed? If so, their network virtualisation is probably installing interfaces that are messing things up. Like I said, "NetworkState" is a very clumsy switch |-:
- launchd doesn't unload the daemon automatically if the network goes down
That's expected behaviour. "KeepAlive" controls when launchd starts your job; stopping your job is your problem. If you want to stop when the network goes away, just use SCF to monitor the network state and, if it goes away and stays away for a reasonable period of time, exit the process. S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware
Thanks Quinn, this helps a lot, I, like Karl, had started going in the wrong direction thinking I could use Lanchd like inetd. Old habits die hard. My daemon checks in with the server every 5 minutes, connection permitting, if we can't connect, try again next time. The server can make a connection anytime, but I don't really need to manage that with Launchd and it works just fine. Using the OnDemand and QueueDirectory keys to manage my Agent is all that is required for basic operation as a LanchAgent and not a LaunchDaemon. I plan to add support for Bonjour, which appears I would need to write a LaunchDaemon. The best example I can find in that regard is AppleVNCServer, but I can ask those questions on Bonjour-Dev. MBP1524:PayLoad nedh$ ps -ax | grep VNC 32 ?? 0:00.02 /System/Library/CoreServices/ RemoteManagement/AppleVNCServer.bundle/Contents/Support/RFBRegisterMDNS 120 ?? 0:00.00 /System/Library/CoreServices/ RemoteManagement/AppleVNCServer.bundle/Contents/Support/ VNCPrivilegeProxy 202 ?? 0:00.05 /System/Library/CoreServices/ RemoteManagement/AppleVNCServer.bundle/Contents/MacOS/AppleVNCServer Seems to me someone could make a few $$ writing a book just on Launchd. Ned On Nov 11, 2008, at 1:28 AM, Quinn wrote:
I have a couple of comments and a couple of questions...
At 12:46 -0500 10/11/08, Karl Moskowski wrote:
Thanks for the info, Ned. Would I need this if my daemon doesn't provide any networks services? (The daemon really just a client for a network service - I made it a daemon because it has to run without a user logged into Mac OS X.) What type of refactoring do you think would be required?
All of the "check in with launchd" stuff is only necessary when you're vending a service and you want to launch on demand. If you're connecting to a service, you shouldn't need it.
Q1: Are you planning to launch on demand, or do you want to launch at startup and keep running?
A launchd daemon that's set to launch at startup will launch well before the network comes up. Keep in mind that the network may / never/ come up, or may come up and go down (repeatedly even), so it's not a case of simply waiting for the network to come up, you have to track the network state.
Q2: Do you want to be running even if there's no possibility of connecting to your network service?
S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/
Apple Developer Relations, Developer Technical Support, Core OS/ Hardware _______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
participants (3)
-
Karl Moskowski
-
Ned Hogan
-
Quinn