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.

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.

Boot sequence with user applications starting before Launch daemons and even system extensions clearly represents a potential security risk. It is very clearly visible when using FileVault. In this case user needs to enter password, OS decrypts volume and then it can startup and launch processes, but very quickly opens user's Desktop and starts to open applications. The bigest problem is that for example Endpoint system extension, which defends computer from infections or Network system extension, which scans network traffic and defends against infected web pages, email, etc. cannot immediately block harmful content. PIDs of these processes are larger than for example Launch Daemons. It means that for example Mail could open very quickly and load new message before Network System extension is loaded and traffic captured and scanned.

We see it especaily on new OS versions running on ARM where it can take up to 10-30 seconds to properly load everything to protect users. That happens when OS is setup with FileVault and user has many, many applications opened - Mail, Calendar, Safari with lots of tabs, Teams, Remote Desktop, etc, etc. When user reboots computer, we clearly see this delay in start up of critical processes that should protect users, especially in corporate environment.

Bootup sequence should look something like this:

  1. System Extenisons
  2. Launch Daemons
  3. Launch Agents
  4. User applications

Is there a way to setup this sequence of process start up? Thanks, Robert

The bigest problem is that for example Endpoint system extension

If you’re talking about Endpoint Security system extensions specifically, they have an option to run early. For the details, see WWDC 2020 Session 10159 Build an Endpoint Security app, starting around 30:25.

If you’re building an ES product, I recommend that you adopt this. If you’re using a third-party ES product, I recommend that you talk to the vendor about this. If you’ve already adopted this and it’s not working, that’s eminently bugworthy.

Share and Enjoy

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

LaunchAgent priority
 
 
Q