Yosemite not starting a system launch agent
Greetings, Here's my problem in a nutshell: I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won't start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd). Here's what my program does: 1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges). 2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful) 3) launchctl start com.qrecall.scheduler (exits with status 1) And the scheduler process is NOT started. All attempts to get it started through launchctl have failed. However, I know that it's installed because if you simply restart the system the scheduler deamon starts running like a champ. Now ... I know what you're going to say: "Dude! You should be using the new launchctl commands introduced in 10.10!" Tried that. I can't seem to get anywhere with it. Basically, I don't know what I'm doing. I've read the man page for the new launchctl about 20 times and I'm still not sure how I should be using it. For per-user agents, it seems pretty obvious that you would bootstrap and address the service in the user/login/gui domain (i.e. launchctl enable user/501/com.qrecall.scheduler). But I don't understand how to treat a system-wide user agent that should be installed in /Library/LaunchAgents. Through trial and error, I've discovered that I can address the current user's instance of the scheduler process for commands like "kill". So this command works: launchctl kill TERM user/501/com.qrecall.scheduler It sends a TERM signal and the daemon restarts. However, I can't find anyway to use the bootstrap command to install it, the enable command won't start it, and the kickstart command says there's no such service. It would seem to make sense that a system-wide agent would have to be installed in the system domain, but this command: sudo launchctl bootstrap system /Library/LaunchAgents/com.qrecall.scheduler results in the error "/Library/LaunchAgents/com.qrecall.scheduler.plist: Service cannot load in requested session" Attempts to use any other domain in the command result in a syntax error, so I'm completely stumped as to how the service should be installed. I've figured out the I can enable and disable the per-user instance, but it has no effect on the running process. In other words, disabling won't halt the service and enabling it won't start it. And don't get me started on unbootstrap, which doesn't appear to be implemented. So, at this point I have my feet planted firmly in mid-air... James Bucanek
Le 23 juin 2015 à 03:31, James Bucanek a écrit :
Greetings,
Here's my problem in a nutshell:
I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won’t start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd).
Hello James, If you allow, some questions for better understanding your context.
Here’s what my program does:
Which program? Some kind of installer?
1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges).
So, do you install the plist yourself, beforehand, or is this done by aforementioned "program"? Could you show us that plist?
2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful)
I guess this is done by the "program". Is it run by a logged in user (in the GUI) and running as that user?
3) launchctl start com.qrecall.scheduler (exits with status 1)
And the scheduler process is NOT started. All attempts to get it started through launchctl have failed.
However, I know that it’s installed because if you simply restart the system the scheduler deamon starts running like a champ.
For any user that logs in? Or for a specific user only? More generally, could you describe what exactly you want to achieve, the workflow you are considering? We could then proceed with some trials at home. ;-)
Now ... I know what you're going to say: "Dude! You should be using the new launchctl commands introduced in 10.10!"
Tried that. I can't seem to get anywhere with it. Basically, I don't know what I'm doing. I've read the man page for the new launchctl about 20 times and I'm still not sure how I should be using it.
[…]
Yes, it’s a pity. Terribly outdated documentation on developer’s site, no source code anymore… A bit as if users on other unix platforms would suddenly have to guess how the init mechanism is working. Axel
On 25 Jun, 2015, at 05:20, Axel Luttgens <axel.luttgens@skynet.be> wrote:
Le 23 juin 2015 à 03:31, James Bucanek a écrit :
Greetings,
Here's my problem in a nutshell:
I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won’t start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd).
Hello James,
If you allow, some questions for better understanding your context.
Here’s what my program does:
Which program? Some kind of installer?
1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges).
So, do you install the plist yourself, beforehand, or is this done by aforementioned "program"?
Could you show us that plist?
2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful)
I guess this is done by the "program". Is it run by a logged in user (in the GUI) and running as that user?
3) launchctl start com.qrecall.scheduler (exits with status 1)
And the scheduler process is NOT started. All attempts to get it started through launchctl have failed.
However, I know that it’s installed because if you simply restart the system the scheduler deamon starts running like a champ.
For any user that logs in? Or for a specific user only?
More generally, could you describe what exactly you want to achieve, the workflow you are considering? We could then proceed with some trials at home. ;-)
Now ... I know what you're going to say: "Dude! You should be using the new launchctl commands introduced in 10.10!"
Tried that. I can't seem to get anywhere with it. Basically, I don't know what I'm doing. I've read the man page for the new launchctl about 20 times and I'm still not sure how I should be using it.
[…]
Yes, it’s a pity. Terribly outdated documentation on developer’s site, no source code anymore… A bit as if users on other unix platforms would suddenly have to guess how the init mechanism is working.
The launchctl(1) and launchd.plist(5) man pages were substantially updated in Yosemite to cover new functionality, address a bunch of clarity errors, and remove stuff that was no longer relevant. launchctl(1) itself also has fairly extensive help for each subcommand. If documentation in either the man pages or launchctl(1)'s help output is unclear/incorrect, please file a bug. -damien
Le 25 juin 2015 à 17:58, Damien Sorresso a écrit :
On 25 Jun, 2015, at 05:20, Axel Luttgens wrote:
[…] Yes, it’s a pity. Terribly outdated documentation on developer’s site, no source code anymore… A bit as if users on other unix platforms would suddenly have to guess how the init mechanism is working.
The launchctl(1) and launchd.plist(5) man pages were substantially updated in Yosemite to cover new functionality, address a bunch of clarity errors, and remove stuff that was no longer relevant. launchctl(1) itself also has fairly extensive help for each subcommand.
Hello Damien, Indeed, those man pages have undergone a deep and nice rewriting. The problem is, they currently are the only launchd-related documentation left. And this is quite problematic for those wanting to have a "grand unified view", so as to be able to answer questions such as: why the hell does /S/L/LD/org.apache.httpd.plist set environment variable XPC_SERVICES_UNAVAILABLE? should I care about such matters when running my own "traditional" server daemon? and, if yes, which matters exactly? And not having the source code at hand anymore just makes things worse, since the ultimate documentation for such a central/crucial piece of the OS has now disappeared.
If documentation in either the man pages or launchctl(1)’s help output is unclear/incorrect, please file a bug.
I don’t know, I’m still reading and experimenting each time I have the opportunity to do so (that is to say, not very often…). As soon as I find a glitch, I’ll let you know. ;-) Many thanks for your reply, Axel
Axel, Thanks for the feedback. I apologize profusely for the delay in my response; I just had too many fires to deal with to give this the attention it needed.
Axel Luttgens <mailto:axel.luttgens@skynet.be> June 25, 2015 at 5:20 AM
Le 23 juin 2015 à 03:31, James Bucanek a écrit :
Greetings,
Here's my problem in a nutshell:
I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won’t start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd).
Hello James,
If you allow, some questions for better understanding your context.
Here’s what my program does:
Which program? Some kind of installer?
More generally, could you describe what exactly you want to achieve, the workflow you are considering? We could then proceed with some trials at home. ;-)
I'm the author of QRecall (www.qrecall.com). It's a backup and archiving solution. The feature of interest to this discussion is the installation of a light-weight scheduler daemon that manages the automated execution of background tasks (backups, maintenance, validity checks, and so on). The scheduler daemon can be installed in one of two ways. Most users install the scheduler as a regular user agent. The scheduler runs only when the user is logged in, and that satisfies 90% of my user base. I have had no problems installing, or uninstalling, the scheduler as a per-user agent on any version of OS X. However, my program also offers the ability to run scheduled tasks when the user is logged out. (In fact, you can even schedule an action to start when you log in or out.) For this to work, the scheduler (obviously), has to run all the time. For that, I install the scheduler as a system-wide agent, instead of a per-user agent. I then employ a little trick to make sure the scheduler runs all the time. (See sidebar.) -- Begin Sidebar -- The installation and running of the scheduler process as a per-user daemon is a bit involved. So for completeness, I've include a brief explanation of what's going on, although it shouldn't have any bering on the issue at hand. So feel free to skip this sidebar, if you're so inclined. Or, dig into it, if you think this is where the problem is. I only run processes as root when absolutely necessary. The scheduler doesn't need to run as root; it needs to run as a regular user, and just for those users with QRecall installed. This is the area where there's a little impedance mismatch between QRecall and OS X. OS X has the concept of a user agent, a system-wide agent, and a system daemon. What is doesn't have is the concept of a "user daemon": a process that runs, for a single user, as that user, and runs all the time, whether the user is logged in or not. A long time ago, I posed this problem to the list and got a great suggestion (I think it was from Jim Luther) that has served me well for years: (1) Install the scheduler as a system-wide agent. OS X will, by default, start a per-user instance of the process for every user that logs in. (2) Have a global configuration file with a list of UIDs that should be running the scheduler all the time. When each per-user instance is started launchd, the scheduler simply consults the list. If it's current UID is on the list, it runs normally. If it isn't on the list, it terminates with a non-zero exit code. (3) Install a system daemon (QRecallKicker). This daemon runs as root and reads the same global list of UIDs. It forks a copy of itself for each UID on the list. Each copy switches to running as that UID (which it can, 'cause it's root), and then does something that will cause OS X to need the bootstrap for that UID. I make a single call to bootstrap_look_up() for a non-existent service. The side effect is that OS X lazily creates the bootstrap for that UID. As part of the bootstrap creation, launchd starts the system-wide agents for that user. The end result is this: When the system starts up, the QRecallKicker daemon "kicks" each of the users that should be running the "always on" version of the scheduler. This creates a bootstrap for that user and starts its instance of the scheduler agent. If any other users log in, their per-user instance of the scheduler is started, and immediately terminates because that user isn't on the list. Once a bootstrap is created, it stay created until OS X restarts. So even if the user logs out, the scheduler continues running. So that's the tortured story of why I install the scheduler as a system-wide agent. -- End Sidebar --
1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges).
So, do you install the plist yourself, beforehand, or is this done by aforementioned "program"?
Could you show us that plist? Here's the 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>KeepAlive</key> <dict> <key>SuccessfulExit</key> <true/> </dict> <key>Label</key> <string>com.qrecall.scheduler</string> <key>LimitLoadToSessionType</key> <string>Background</string> <key>ProgramArguments</key> <array> <string>/Library/Application Support/QRecall/QRecallScheduler</string> </array> <key>RunAtLoad</key> <true/> </dict> </plist>
2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful)
I guess this is done by the "program". Is it run by a logged in user (in the GUI) and running as that user?
Here's how the installation of the system-wide agent is accomplished: (1) A privileged helper service has already been installed via SMJobBless(). (2) When the scheduler needs to be installed this way, the helper service is run (as root) with instructions to install the scheduler. The helper then: (2)(a) Creates a .plist for the agent and copies it to /Library/LaunchAgents/com.qrecall.scheduler.plist, assigning it the correct ownership (root) and permissions (-rw-r--r--) required by launchd. (2)(b) Runs the command 'launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist' as root. (I've always wondered if I should rewrite these steps to use SMJobSubmit, but I now see that it's already deprecated.) Note that this only happens when the scheduler needs to be installed in it's "daemon" version. Installation and removal of the per-user scheduler agent is handled entirely in userland by the main app. In the past (pre-10.10), this has always installed and started the agent process immediately.
3) launchctl start com.qrecall.scheduler (exits with status 1)
And the scheduler process is NOT started. All attempts to get it started through launchctl have failed.
However, I know that it’s installed because if you simply restart the system the scheduler deamon starts running like a champ.
For any user that logs in? Or for a specific user only? The scheduler is only going to start for the user's it's configured to run for. Having said that, it doesn't appear to start for any user when the 'launchctl load' command is issued. Although, as I've mentioned before, if you restart the system and log back in, it starts and runs just fine.
I hope that this more clearly explains what I'm trying to accomplish. Actually, I've already accomplished it; this has been working for years but now seems (slightly) broken in 10.10 and 10.11. If the solution is to use the new launchctl command syntax, I'll jump right on it ... just as soon as someone can help me understand what command I should be issuing. I've left the original message attached, since it's been so long since I posted it. Thanks again, in advance, for all the help and ideas. James Bucanek
James Bucanek <mailto:subscriber@gloaming.com> June 22, 2015 at 6:31 PM Greetings,
Here's my problem in a nutshell:
I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won't start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd).
Here's what my program does:
1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges).
2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful)
3) launchctl start com.qrecall.scheduler (exits with status 1)
And the scheduler process is NOT started. All attempts to get it started through launchctl have failed.
However, I know that it's installed because if you simply restart the system the scheduler deamon starts running like a champ.
Now ... I know what you're going to say: "Dude! You should be using the new launchctl commands introduced in 10.10!"
Tried that. I can't seem to get anywhere with it. Basically, I don't know what I'm doing. I've read the man page for the new launchctl about 20 times and I'm still not sure how I should be using it.
For per-user agents, it seems pretty obvious that you would bootstrap and address the service in the user/login/gui domain (i.e. launchctl enable user/501/com.qrecall.scheduler).
But I don't understand how to treat a system-wide user agent that should be installed in /Library/LaunchAgents. Through trial and error, I've discovered that I can address the current user's instance of the scheduler process for commands like "kill". So this command works:
launchctl kill TERM user/501/com.qrecall.scheduler
It sends a TERM signal and the daemon restarts.
However, I can't find anyway to use the bootstrap command to install it, the enable command won't start it, and the kickstart command says there's no such service.
It would seem to make sense that a system-wide agent would have to be installed in the system domain, but this command:
sudo launchctl bootstrap system /Library/LaunchAgents/com.qrecall.scheduler
results in the error "/Library/LaunchAgents/com.qrecall.scheduler.plist: Service cannot load in requested session"
Attempts to use any other domain in the command result in a syntax error, so I'm completely stumped as to how the service should be installed.
I've figured out the I can enable and disable the per-user instance, but it has no effect on the running process. In other words, disabling won't halt the service and enabling it won't start it.
And don't get me started on unbootstrap, which doesn't appear to be implemented.
So, at this point I have my feet planted firmly in mid-air...
James Bucanek
James, Your plist probably has the LimitLoadToSessionType key set to Background, which will prevent it from loading outside of a user's background session. So when you do a regular `launchctl load` from a Terminal window (for example), you're targeting the Aqua session, and launchd says no. Similarly, if you try and load it into the system session (either by running launchctl(1) under sudo(1) or by using the bootstrap subcommand with a "system" target), launchd will also say no. If you remove the LimitLoadToSession type key, you'll be able to load the job wherever you'd like. -damien On 22 Jun, 2015, at 18:31, James Bucanek <subscriber@gloaming.com> wrote:
Greetings,
Here's my problem in a nutshell:
I have a simple scheduler daemon that runs in the background for logged in users. The problem is that it won't start when installed in Yosemite (seems to start in all previous versions of OS X that use launchd).
Here's what my program does:
1) I install the com.qrecall.sheduler.plist in /Library/LaunchAgents/ (with the correct ownership and access privileges).
2) launchctl load -S Background /Library/LaunchAgents/com.qrecall.scheduler.plist (successful)
3) launchctl start com.qrecall.scheduler (exits with status 1)
And the scheduler process is NOT started. All attempts to get it started through launchctl have failed.
However, I know that it's installed because if you simply restart the system the scheduler deamon starts running like a champ.
Now ... I know what you're going to say: "Dude! You should be using the new launchctl commands introduced in 10.10!"
Tried that. I can't seem to get anywhere with it. Basically, I don't know what I'm doing. I've read the man page for the new launchctl about 20 times and I'm still not sure how I should be using it.
For per-user agents, it seems pretty obvious that you would bootstrap and address the service in the user/login/gui domain (i.e. launchctl enable user/501/com.qrecall.scheduler).
But I don't understand how to treat a system-wide user agent that should be installed in /Library/LaunchAgents. Through trial and error, I've discovered that I can address the current user's instance of the scheduler process for commands like "kill". So this command works:
launchctl kill TERM user/501/com.qrecall.scheduler
It sends a TERM signal and the daemon restarts.
However, I can't find anyway to use the bootstrap command to install it, the enable command won't start it, and the kickstart command says there's no such service.
It would seem to make sense that a system-wide agent would have to be installed in the system domain, but this command:
sudo launchctl bootstrap system /Library/LaunchAgents/com.qrecall.scheduler
results in the error "/Library/LaunchAgents/com.qrecall.scheduler.plist: Service cannot load in requested session"
Attempts to use any other domain in the command result in a syntax error, so I'm completely stumped as to how the service should be installed.
I've figured out the I can enable and disable the per-user instance, but it has no effect on the running process. In other words, disabling won't halt the service and enabling it won't start it.
And don't get me started on unbootstrap, which doesn't appear to be implemented.
So, at this point I have my feet planted firmly in mid-air...
James Bucanek
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
Damien, Thanks for the suggestion, and apologies for the tardy reply; I just got buried under twenty other to-do items that were higher on the list. I tried removing the LimitLoadToSessionType entry from my agent's plist, but it doesn't make any difference. When trying to install it as a system-wide agent, the process still doesn't start. My reading of LimitLoadToSessionType would lead me to believe that it's applicable to my service, which *is* an agent. It runs as a regular user, and the docs would indicate that this property is just a hint to the load balancer on how to constrain its use of CPU/memory/IO. It doesn't make sense that it would keep the process from starting in the first place. Anyway, I'm replying to Axel's message with a complete description of what I'm trying to accomplish and exactly what's not working. James
Damien Sorresso <mailto:dsorresso@apple.com> June 25, 2015 at 8:53 AM James,
Your plist probably has the LimitLoadToSessionType key set to Background, which will prevent it from loading outside of a user's background session. So when you do a regular `launchctl load` from a Terminal window (for example), you're targeting the Aqua session, and launchd says no. Similarly, if you try and load it into the system session (either by running launchctl(1) under sudo(1) or by using the bootstrap subcommand with a "system" target), launchd will also say no.
If you remove the LimitLoadToSession type key, you'll be able to load the job wherever you'd like. -damien
James, Some replies inline... On 22 Jul, 2015, at 17:46, James Bucanek <subscriber@gloaming.com> wrote:
Damien,
Thanks for the suggestion, and apologies for the tardy reply; I just got buried under twenty other to-do items that were higher on the list.
I tried removing the LimitLoadToSessionType entry from my agent's plist, but it doesn't make any difference. When trying to install it as a system-wide agent, the process still doesn't start.
In launchd's lexicon, "system-wide agent" is a conflict of terminology. System-wide things are, by definition, daemons. Agents are things which run on a per-user basis (cf. launchd(8)). So the real question is about the desired lifecycle of your job. Do you want it to run when a user logs in and to go away when the user logs out? Or do you want it to be available regardless of any user being logged in?
My reading of LimitLoadToSessionType would lead me to believe that it's applicable to my service, which *is* an agent. It runs as a regular user, and the docs would indicate that this property is just a hint to the load balancer on how to constrain its use of CPU/memory/IO. It doesn't make sense that it would keep the process from starting in the first place.
Wow, no that's not at all what that key is for. Please file a bug explaining how the documentation misled you into that impression so we can make it clearer! Session types are basically collections of certain kinds of jobs. The "Aqua" session is all the jobs associated with a graphical login on the console. By default, if your job is an agent, it is loaded into the Aqua session. (That is, if no LimitLoadToSessionType key is present.) The Background session is a collection of jobs that can run on behalf of a user even if that user is not logged in at the graphical console. They might be doing things like performing Spotlight indexing on that user's home directory even when that user isn't logged in for example. So if you have a vanilla Terminal prompt and do a `launchctl load`, your plist will attempt to load in the Aqua session. If that service has LimitLoadToSessionType set to "Background", then that load will fail because it's attempting to load in the Aqua session and your service has expressed that it should only load in the Background session. -damien
Anyway, I'm replying to Axel's message with a complete description of what I'm trying to accomplish and exactly what's not working.
James
Damien Sorresso <mailto:dsorresso@apple.com> June 25, 2015 at 8:53 AM James,
Your plist probably has the LimitLoadToSessionType key set to Background, which will prevent it from loading outside of a user's background session. So when you do a regular `launchctl load` from a Terminal window (for example), you're targeting the Aqua session, and launchd says no. Similarly, if you try and load it into the system session (either by running launchctl(1) under sudo(1) or by using the bootstrap subcommand with a "system" target), launchd will also say no.
If you remove the LimitLoadToSession type key, you'll be able to load the job wherever you'd like. -damien
Damien Sorresso <mailto:dsorresso@apple.com> July 22, 2015 at 6:19 PM James,
Some replies inline...
On 22 Jul, 2015, at 17:46, James Bucanek <subscriber@gloaming.com <mailto:subscriber@gloaming.com>> wrote:
Damien,
Thanks for the suggestion, and apologies for the tardy reply; I just got buried under twenty other to-do items that were higher on the list.
I tried removing the LimitLoadToSessionType entry from my agent's plist, but it doesn't make any difference. When trying to install it as a system-wide agent, the process still doesn't start.
In launchd's lexicon, "system-wide agent" is a conflict of terminology. System-wide things are, by definition, daemons. Agents are things which run on a per-user basis (cf. launchd(8)). So the real question is about the desired lifecycle of your job. Do you want it to run when a user logs in and to go away when the user logs out? Or do you want it to be available regardless of any user being logged in? That's the problem; I don't know what to call them. It's an agent, but it's an agent for all users (/Library/LaunchAgents) to distinguish it for exclusively for an individual user (~/Library/LaunchAgents). And it should run in the context of the user's bootstrap, not just within the GUI login.
My reading of LimitLoadToSessionType would lead me to believe that it's applicable to my service, which *is* an agent. It runs as a regular user, and the docs would indicate that this property is just a hint to the load balancer on how to constrain its use of CPU/memory/IO. It doesn't make sense that it would keep the process from starting in the first place.
Wow, no that's not at all what that key is for. Please file a bug explaining how the documentation misled you into that impression so we can make it clearer! I think I got this confused with ProcessType. Both have a "Background" type.
I'll file a bug report on the docs, but one problem that I run into is that terms are often never defined. For example, the LimitLoadToSessionType section in man 5 launchd.plist describes it thusly: "LimitLoadToSessionType <string or array or strings> This configuration file only applies to sessions of the type(s) specified." But the descriptions of what "type(s)" can be is never defined or explained in the man pages for launchd.plist, launchctl, or launchd. I'm sure the description of what LimitLoadToSessionType does is accurate, but I still left wondering what values are valid or what they mean. :)
Session types are basically collections of certain kinds of jobs. The "Aqua" session is all the jobs associated with a graphical login on the console. By default, if your job is an agent, it is loaded into the Aqua session. (That is, if no LimitLoadToSessionType key is present.)
The Background session is a collection of jobs that can run on behalf of a user even if that user is not logged in at the graphical console. They might be doing things like performing Spotlight indexing on that user's home directory even when that user isn't logged in for example.
What I want, and I think that's what I've configured in the .plist, is a per-user Agent running in the Background session, for all users. The .plist is placed in /Library/LaunchAgents and the LimitLoadToSessionType is set to Background. (See my earlier message. It has all the details.)
So if you have a vanilla Terminal prompt and do a `launchctl load`, your plist will attempt to load in the Aqua session. If that service has LimitLoadToSessionType set to "Background", then that load will fail because it's attempting to load in the Aqua session and your service has expressed that it should only load in the Background session.
In my case, the 'launchctl load ...' command is being executed via NSTask launched from a helper running as root, itself launched from a privileged helper service installed via SMJobBless. I don't know if this puts launchctl in the context of Background session of the user or in the root System session. James
On 22 Jul, 2015, at 22:49, James Bucanek <subscriber@gloaming.com> wrote:
Damien Sorresso <mailto:dsorresso@apple.com> July 22, 2015 at 6:19 PM James,
Some replies inline...
On 22 Jul, 2015, at 17:46, James Bucanek <subscriber@gloaming.com <mailto:subscriber@gloaming.com>> wrote:
Damien,
Thanks for the suggestion, and apologies for the tardy reply; I just got buried under twenty other to-do items that were higher on the list.
I tried removing the LimitLoadToSessionType entry from my agent's plist, but it doesn't make any difference. When trying to install it as a system-wide agent, the process still doesn't start.
In launchd's lexicon, "system-wide agent" is a conflict of terminology. System-wide things are, by definition, daemons. Agents are things which run on a per-user basis (cf. launchd(8)). So the real question is about the desired lifecycle of your job. Do you want it to run when a user logs in and to go away when the user logs out? Or do you want it to be available regardless of any user being logged in? That's the problem; I don't know what to call them. It's an agent, but it's an agent for all users (/Library/LaunchAgents) to distinguish it for exclusively for an individual user (~/Library/LaunchAgents). And it should run in the context of the user's bootstrap, not just within the GUI login.
My reading of LimitLoadToSessionType would lead me to believe that it's applicable to my service, which *is* an agent. It runs as a regular user, and the docs would indicate that this property is just a hint to the load balancer on how to constrain its use of CPU/memory/IO. It doesn't make sense that it would keep the process from starting in the first place.
Wow, no that's not at all what that key is for. Please file a bug explaining how the documentation misled you into that impression so we can make it clearer! I think I got this confused with ProcessType. Both have a "Background" type.
I'll file a bug report on the docs, but one problem that I run into is that terms are often never defined. For example, the LimitLoadToSessionType section in man 5 launchd.plist describes it thusly:
"LimitLoadToSessionType <string or array or strings> This configuration file only applies to sessions of the type(s) specified."
But the descriptions of what "type(s)" can be is never defined or explained in the man pages for launchd.plist, launchctl, or launchd. I'm sure the description of what LimitLoadToSessionType does is accurate, but I still left wondering what values are valid or what they mean. :)
Yes, please file a documentation bug. This could be made clearer.
Session types are basically collections of certain kinds of jobs. The "Aqua" session is all the jobs associated with a graphical login on the console. By default, if your job is an agent, it is loaded into the Aqua session. (That is, if no LimitLoadToSessionType key is present.)
The Background session is a collection of jobs that can run on behalf of a user even if that user is not logged in at the graphical console. They might be doing things like performing Spotlight indexing on that user's home directory even when that user isn't logged in for example. What I want, and I think that's what I've configured in the .plist, is a per-user Agent running in the Background session, for all users. The .plist is placed in /Library/LaunchAgents and the LimitLoadToSessionType is set to Background. (See my earlier message. It has all the details.)
So if you have a vanilla Terminal prompt and do a `launchctl load`, your plist will attempt to load in the Aqua session. If that service has LimitLoadToSessionType set to "Background", then that load will fail because it's attempting to load in the Aqua session and your service has expressed that it should only load in the Background session. In my case, the 'launchctl load ...' command is being executed via NSTask launched from a helper running as root, itself launched from a privileged helper service installed via SMJobBless. I don't know if this puts launchctl in the context of Background session of the user or in the root System session.
That is your problem. In that context, `launchctl load` will attempt to load your job as a daemon because it is running as root in the root Mach bootstrap. One thing that's critical to understand is that there's nothing about the contents of your plist which identifies it as a daemon or agent; the same plist can be loaded into multiple contexts. Each context can have sessions within it. As it turns out, the only place this matters is the per-user context, which has Background and Aqua. The intended effect of `launchctl load` and friends is determined by your calling context. This is why the new bootstrap subcommand introduced in Yosemite takes an explicit parameter identifying the context you want to bootstrap the job into. Try changing your NSTask invocation in your helper tool to this: launchctl bootstrap user/$UID /path/to/plist On earlier versions of OS X, this should also work: launchctl asuser $UID launchctl load /path/to/plist -damien
Damian, Thanks for sticking with me. OK, here's what I've tried:
Damien Sorresso <mailto:dsorresso@apple.com> July 23, 2015 at 8:35 AM On 22 Jul, 2015, at 22:49, James Bucanek <subscriber@gloaming.com <mailto:subscriber@gloaming.com>> wrote:
Damien Sorresso <mailto:dsorresso@apple.com> July 22, 2015 at 6:19 PM
That is your problem. In that context, `launchctl load` will attempt to load your job as a daemon because it is running as root in the root Mach bootstrap. One thing that's critical to understand is that there's nothing about the contents of your plist which identifies it as a daemon or agent; the same plist can be loaded into multiple contexts. Each context can have sessions within it. As it turns out, the only place this matters is the per-user context, which has Background and Aqua. The intended effect of `launchctl load` and friends is determined by your calling context.
I'm getting that.
This is why the new bootstrap subcommand introduced in Yosemite takes an explicit parameter identifying the context you want to bootstrap the job into. Try changing your NSTask invocation in your helper tool to this:
launchctl bootstrap user/$UID /path/to/plist
Here's the experiment I performed. I uninstalled all of my software, created a test .plist file on my desktop that points to a working version of my user agent, and issued the following command sudo launchctl bootstrap user/501 /Users/james/Desktop/com.qrecall.scheduler.plist Here's what worked: - The QRecallScheduler executable started up for user 501 (yea!). - Using 'launchctrl print user/501' and 'launchctl print user/501/com.qrecall.scheduler' I can see that the agent was installed. Where's what doesn't work: The agent only runs for user 501. When I log in with another user, the agent doesn't start. Now this is consistent with my understanding of the "user/501" domain; this syntax refers to the session belonging to user 501 and only user 501. This is not what I'm trying to accomplish. (I have the per-user stuff working just fine). I'm trying, as an administrator (root), to install a user agent that will run FOR ALL USERS. This is my frustration with the documentation for the new launchctl. I can see that "system/" applies to the root system (daemons). I understand that "user/PID" applies to the context of a single user, as does its various synonyms (login/ASID, gui/UID, session/ASID, ...). What I can't figure out is the syntax for addressing a user agent to be started for ALL users. Said another way, how do you say to launchctl "I, the administrator, have installed a user agent that needs to be installed and started for every logged in user, here's its .plist"? After that command, if there were three users logged in, I'd expect three instances of my agent to start. I tried "user/*". It doesn't work. ;) Finally, I notice that 'launchctl bootstrap ...' does not copy the .plist to the /Library/LaunchAgents or ~/Library/LaunchAgents folder, and after restarting the system my agent is no longer running and no longer appears in 'launchctl print user/501'. I infer from this that to permanently install a user agent, I'm still responsible for copying the .plist to the appropriate directory (/Library/LaunchAgents or ~/Library/LaunchAgents). Having now vented my angst over this whole mess, I'm considering a solution that bypasses the need to install an agent for all users. You've helped me by clearly describing the difference between a "Background" session for a user and the "Aqua" session for a user. I'm thinking now that I don't need to install a user agent for all users. I just need to install a "Background" agent for each users that wants the scheduler to run when they are logged out, and I can do that without needing admin authorization. I still need the "kicker" system daemon to create the session for each user (with a scheduler installed) before they've logged in, but that should also start all of the per-user "Background" agents in ~/Library/LaunchAgents for that user, correct? James
Le 23 juil. 2015 à 17:35, Damien Sorresso a écrit :
On 22 Jul, 2015, at 22:49, James Bucanek wrote:
[…] In my case, the 'launchctl load ...' command is being executed via NSTask launched from a helper running as root, itself launched from a privileged helper service installed via SMJobBless. I don't know if this puts launchctl in the context of Background session of the user or in the root System session.
That is your problem. In that context, `launchctl load` will attempt to load your job as a daemon because it is running as root in the root Mach bootstrap. One thing that's critical to understand is that there's nothing about the contents of your plist which identifies it as a daemon or agent; the same plist can be loaded into multiple contexts. Each context can have sessions within it. As it turns out, the only place this matters is the per-user context, which has Background and Aqua.
Hello Damien, Only those two contexts? No login context (or LoginWindow context, whatever it is called)?
The intended effect of `launchctl load` and friends is determined by your calling context.
This is why the new bootstrap subcommand introduced in Yosemite takes an explicit parameter identifying the context you want to bootstrap the job into. Try changing your NSTask invocation in your helper tool to this:
launchctl bootstrap user/$UID /path/to/plist
Yes, I noticed this was working while experimenting around James’ plist; but this happened only intuitively, by guessing that the bootstrap subcommand could well have been devised so as to bypass the calling context. Could it be that such matters are already extensively/systematically documented somewhere, and that I just missed it (shame on me)?
On earlier versions of OS X, this should also work:
launchctl asuser $UID launchctl load /path/to/plist
I’ll take the opportunity of the above for asking another question. From the launchctl(1) man page: In the discussion of the -S sessiontype option, three "contexts" (or "sessions", which seems to be taken as a synonym) are distinguished at the per-user level: 1a. Aqua 1b. Background 1c. LoginWindow In the discussion of the asuser subcommand, one may read about: 2b. the target user’s bootstrap In the description of the various target domains, one has: 3a. login/<asid>, gui/<uid> 3b. user/<uid> May it be said that, for example, 1b, 2b and 3b are covering the same concept, in spite of quite different terminologies? TIA, Axel
participants (3)
-
Axel Luttgens
-
Damien Sorresso
-
James Bucanek