Understanding bootstrap idea in different versions of MacOS
Hello I understand that this is not an apple way to respond about obsolete versions of their software. But i am hoping some of launchd developers look through this list, and who are aware of pecularities of their child :) i am trying to launch an agent programmatically (not only automatically when the system is started), but in a certain moment. I mean, a user installs an application, and he is happy having an agent run as soon as an app is installed. as i've been told on this list some time ago, it can be done only by exec'ing "launchctl -w load [plist file path]", as long as OS X does not provide any explicit ways to communicate to per user launchd service and ask it to process a plist file. I assume that launchd "interface" could be retrieved by reading sources of launchctl (i've heard they are available), but my qualification doesnt allow me to do that so far. The problem i've run into was launchctl and launchd acting differently on different versions of OS X, partly because launchctl changed the way it searches for the right launchd instance (so i've been told on this list) from the per-bootstrap to per-user, In archives i found some ways of "talking" to the right instance of launchd - like, specifying "-S" parameter, or using "bslist" param. They seem to work differently not only on OS X 10.5 and 10.6, but even inside 10.5 builds (for example, while on 10.5.6 sudo launchctl load -w myagent.plist launches an agent, on 10.5.4 users get "Socket not connected"). Could you please explain, how to 'talk' to the right launchd and what is the difference in the way of 'talking' in different versions of OS X? Thanx
On 24 Jan 2011, at 18:35, eveningnick eveningnick wrote:
Could you please explain, how to 'talk' to the right launchd and what is the difference in the way of 'talking' in different versions of OS X?
For the initial install cycle my standard hack is to use "launchctl bsexec". This allows you to start a process in a specific bootstrap context. So, let's say you're installing from the root context (perhaps you're a system management package that's installing its agent in response to a command received over the network), you can do the following: 1. install the agent plist in /Library/LaunchAgents 2. find all the loginwindow processes 3. exclude those running as root [1] 4. for each remaining loginwindow process, do the following launchctl bsexec <pid> chroot -u <user> / launchctl load /Library/LaunchAgents/<plist> The "launchctl bsexec" causes the chroot to run in the bootstrap namespace of the loginwindow whose <pid> you supply. The chroot sets both the EUID and RUID of the "launchctl load" to the specified <uid>. Without this the "launchctl load" runs as root and ends up talking to the global launchd. The "launchctl load" just loads the agent into the correct context. The issues with this approach are legion, including the following that spring immediately to mind: o It relies on there being a loginwindow for each GUI context, and that the loginwindows EUID is the user associated with that context. o It is subject to nasty race conditions. o You can't target a loginwindows running at the login screen (which is fine if you're creating a GUI launchd agent, but is a serious problem if you're creating a pre-login launchd agent). All in all, it's a horrible hack and I'd rather folks didn't use it. Indeed, if the choice is between a) forcing a restart, and b) doing this, I'm not sure what I'd recommend. Keep in mind that this is only necessary for the first install of your agent. After that you should use the IPC channel between your daemon and its agents to keep everything up-to-date. S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware [1] These are loginwindow processes sitting at the login screen, and targetting that namespace is hard.
Thank you for a detailed explanation
participants (2)
-
eveningnick eveningnick
-
Quinn "The Eskimo!"