Hello, I'm writing a launchd agent that opens a TCP listening socket. Ideally, I'd like launchd to open and listen to the socket via SockServiceName so my agent only gets launched as-needed. The problem is I'd like to listen to the same port (e.g. 12345), no matter which user is logged in. This is fine when there's only one user logged in, but as soon as fast user switching comes into play, the socket gets an "address already in use" when the second user logs in. This is to be expected, I suppose. But is there any way to have launchd only listen to the socket when the user is the "active" user, and have it *not* listen when the user gets switched out, due to fast user switching? At first glance the LimitLoadToSessionType looked promising, but it doesn't look like any of those will do that. The solution I'm currently entertaining uses launchd to always launch my agent, and have my agent do the socket listening. I can then use the user switch notification to close down the listening port when the session is deactivated and open it when activated. Thanks, -Dave
Dave, The Apple way to solve this problem is to use Bonjour with a dynamic port assignment. Just use port zero, and set Bonjour to true like so: <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>Bonjour</key> <true/> <key>SockServiceName</key> <string>0</string> </dict> </dict> davez On May 22, 2008, at 11:38 AM, Dave Dribin wrote:
Hello,
I'm writing a launchd agent that opens a TCP listening socket. Ideally, I'd like launchd to open and listen to the socket via SockServiceName so my agent only gets launched as-needed.
The problem is I'd like to listen to the same port (e.g. 12345), no matter which user is logged in. This is fine when there's only one user logged in, but as soon as fast user switching comes into play, the socket gets an "address already in use" when the second user logs in.
This is to be expected, I suppose. But is there any way to have launchd only listen to the socket when the user is the "active" user, and have it *not* listen when the user gets switched out, due to fast user switching?
At first glance the LimitLoadToSessionType looked promising, but it doesn't look like any of those will do that.
The solution I'm currently entertaining uses launchd to always launch my agent, and have my agent do the socket listening. I can then use the user switch notification to close down the listening port when the session is deactivated and open it when activated.
Thanks,
-Dave
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
On May 22, 2008, at 2:01 PM, Dave Zarzycki wrote:
Dave,
The Apple way to solve this problem is to use Bonjour with a dynamic port assignment. Just use port zero, and set Bonjour to true like so:
<key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>Bonjour</key> <true/> <key>SockServiceName</key> <string>0</string> </dict> </dict>
That's what I thought, but I'm thinking this won't quite work for this case. Our agent is actually an HTTP server, and we hand out URLs to stuff it serves up, e.g. http://localhost:12345/foo. If we use a dynamic port, even with Bonjour, our URLs are no longer valid. Unless there's a way to specify Bonjour ports in URLs? I thought that only worked for host names, though (i.e. <name>.local). -Dave
On May 22, 2008, at 12:05 PM, Dave Dribin wrote:
On May 22, 2008, at 2:01 PM, Dave Zarzycki wrote:
Dave,
The Apple way to solve this problem is to use Bonjour with a dynamic port assignment. Just use port zero, and set Bonjour to true like so:
<key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>Bonjour</key> <true/> <key>SockServiceName</key> <string>0</string> </dict> </dict>
That's what I thought, but I'm thinking this won't quite work for this case. Our agent is actually an HTTP server, and we hand out URLs to stuff it serves up, e.g. http://localhost:12345/foo. If we use a dynamic port, even with Bonjour, our URLs are no longer valid. Unless there's a way to specify Bonjour ports in URLs? I thought that only worked for host names, though (i.e. <name>.local).
Dave, In theory, the Back-to-my-Mac feature of Mac OS X Leopard should make this possible. One would just need to go to the "Bonjour" submenu of the "Bookmarks" menu in Safari.app. davez
On May 22, 2008, at 2:07 PM, Dave Zarzycki wrote:
Dave,
In theory, the Back-to-my-Mac feature of Mac OS X Leopard should make this possible. One would just need to go to the "Bonjour" submenu of the "Bookmarks" menu in Safari.app.
Yeah, I can see it in Safari if I set the Bonjour service to "http". However, if you click on that link, it sets the url to something like: http://assam.local.:59972/ If I unload and reload the agent, this port number is no longer valid, and I get a different URL: http://assam.local.:59978/ As far as I can tell, this means HTTP URLs cannot be consistent across launchd invocations, which won't work for me, in this case. Unless there's some way to do Bonjour port lookups? FWIW, I'm using the SampleD example and I've modified its plist to have this: <key>Sockets</key> <dict> <key>MyListenerSocket</key> <dict> <key>Bonjour</key> <string>http</string> <key>SockServiceName</key> <string>0</string> </dict> </dict> -Dave
On Thu, May 22, 2008 at 8:28 PM, Dave Dribin <dave-ml@dribin.org> wrote:
As far as I can tell, this means HTTP URLs cannot be consistent across launchd invocations, which won't work for me, in this case. Unless there's some way to do Bonjour port lookups?
Well, the flip side of the Bonjour way of doing things is that you don't store URLs, you store service names, and they are resolved at the last minute. But if you need to give out URLs for whatever reason, that won't work for you. Have you considered having a LaunchDaemon listen on the port and forward requests to the active GUI user? See http://developer.apple.com/technotes/tn2005/tn2083.html#SECBOOTSTRAPNAMESPAC... (read the whole technote from beginning to end, if you haven't already). Hamish
I'm sorry, I made a mistake, it should look like so: <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>Bonjour</key> <string>MyServiceName</string> <key>SockServiceName</key> <string>0</string> </dict> </dict> On May 22, 2008, at 12:01 PM, Dave Zarzycki wrote:
Dave,
The Apple way to solve this problem is to use Bonjour with a dynamic port assignment. Just use port zero, and set Bonjour to true like so:
<key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>Bonjour</key> <true/> <key>SockServiceName</key> <string>0</string> </dict> </dict>
davez
On May 22, 2008, at 11:38 AM, Dave Dribin wrote:
Hello,
I'm writing a launchd agent that opens a TCP listening socket. Ideally, I'd like launchd to open and listen to the socket via SockServiceName so my agent only gets launched as-needed.
The problem is I'd like to listen to the same port (e.g. 12345), no matter which user is logged in. This is fine when there's only one user logged in, but as soon as fast user switching comes into play, the socket gets an "address already in use" when the second user logs in.
This is to be expected, I suppose. But is there any way to have launchd only listen to the socket when the user is the "active" user, and have it *not* listen when the user gets switched out, due to fast user switching?
At first glance the LimitLoadToSessionType looked promising, but it doesn't look like any of those will do that.
The solution I'm currently entertaining uses launchd to always launch my agent, and have my agent do the socket listening. I can then use the user switch notification to close down the listening port when the session is deactivated and open it when activated.
Thanks,
-Dave
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
participants (3)
-
Dave Dribin
-
Dave Zarzycki
-
Hamish Allan