LaunchAgent priority

My LaunchAgent is launched when a user logs in. However, it is launched AFTER all Applications that were still open at logout have been restored.

Is it possible to increase the priority of a LaunchAgent so that it runs before Applications are restored? I tried setting the Nice value in the plist to -20 but that had no effect.

This problem can easily be reproduced by sudo reboot in Terminal when there are multiple applications open. At login all Applications are restored.

Replies

However, it is launched AFTER all Applications that were still open at logout have been restored.

That’s not quite right. launchd uses an on-demand architecture. If one of those launching apps generates demand for a service provided by your agent, it’ll launch right away. However, I’m presuming that your agent isn’t demand based — that is, it’s being launched always, using KeepAlive or one of its older alternatives — and thus there’s no demand in play. In that case then, yes, jobs without demand have a low priority.

Is it possible to increase the priority of a LaunchAgent so that it runs before Applications are restored?

No.

Why does this matter to you?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The plist contains: <key>KeepAlive</key> <true/>

Having this agent run as soon as possible after login is important because it is part of a remote access product and the launch agent is used to acknowledge to a remote client that the user has logged in. From the system log I can see on an older intel Mac that the agent is not run until 20 seconds after login in the case when the system rebooted with a lof of applications open. All the applications can be seen starting up before the launch agent runs.

Would a login item potentially be launched sooner at login?

All the applications can be seen starting up before the launchd agent runs.

Right. This is a deliberate design choice. The goal is to free CPU cycles to get the user up and running as soon as possible after login. AFAIK the only way around it is to artificially induce demand for your agent.

Having this agent run as soon as possible after login is important because it is part of a remote access product and the launch agent is used to acknowledge to a remote client that the user has logged in.

Have you testing the ‘mini Buddy’ case, that is, the small setup assistant that runs when, for example, you do a minor update of the OS?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Do you have a reference so I could read up on the 'mini buddy' approach please?

I have also tried having my Launch Daemon attempt to connect to the Launch Agent via XPC. I know this is not recommended but I was hoping even just attempting to connect to the launch agent might create this "artificial demand" and kick the Launch Agent into life. However, it does not seem to be working. What would be a better way to create this artificial demand?

I also noticed that any attempt to force my LaunchAgent to start from terminal (via SSH session) seems to be ignored. The LaunchAgent still does not start running until all the Applications have been restored. For example, the follow has no effect:

launchctl load -w /Library/LaunchAgents/com.mycompany.myproduct.myagent.plist

Do you have a reference so I could read up on the 'mini buddy' approach please?

OK, some background:

  • Mac Buddy is the informal name for the setup assistant that run when you first boot the Mac [1].

  • By extension, Mini Buddy is the setup assistant that runs when you log in, typically after a software update.

IIRC Mini Buddy puts the GUI login session into ‘on-demand jobs only’ mode, just like app restore, except in that case it continues indefinitely, only ending when the user has finished the setup. This is a serious challenge for screen sharing products.

I have also tried having my Launch Daemon attempt to connect to the Launch Agent via XPC.

That won’t work because of layered namespaces. The fact that you tried it suggests that you’re missing key details about macOS’s layered architecture. I recommend reading the Execution Contexts section of Technote 2083 Daemons and Agents. It’s not longer 100% accurate, but it’s still accurate enough to be helpful.

I also noticed that any attempt to force my LaunchAgent to start from terminal (via SSH session) seems to be ignored.

That’s not going to work for so many reasons )-: To start, a load is different from a start. In this case the job is loaded already, it’s just not starting. So running a launchctl load won’t help; you’d need a launchctl start.

But that won’t work either because your shell is running in an SSH session, not the GUI login session. With modern launchctl commands, like kickstart, you can target one session from another, and that might be an interesting test, but…

What would be a better way to create this artificial demand?

I have no supported suggestions on this front. Everything that works is a hack )-:

My advice is that you read the launchd.plist man page, study the various types of demand that it supports, a craft a solution based on one of those.

Oh, and whatever approach you take, please file a bug about this. The system should support a way for screen sharing products to solve this problem.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] It may have actually been a code name at one point, but at this point it’s just part of the general lexicon.