launchd not starting service for AD users

Apple M2 Pro MacOs: 13.6 (22G120)

In my system extension installer's postInstall script I have launch agent configured for the app as below:

launchctl enable gui/$user_uid/com.mycompany.client.myproduct
launchctl bootstrap gui/501 /Library/LaunchAgents/com.mycompany.myproduct.plist

When I install the software using a local user, the service works fine without any issue and the service is shown listed in 'launchctl list' command:

% launchctl list | grep -i mycompany
84714	0	com.mycompany.client.myproduct

But when I login using on the same machine using a AD (Active Directory) user, the service/agent doesnt start and I don't see any entry service listed in 'launchctl list'.

This is how my plist file looks like:

% defaults read /Library/LaunchAgents/com.mycompany.myproduct.plist
{
    CFBundleVersion = "200.200.200.200";
    KeepAlive = 1;
    Label = "com.mycompany.client.myproduct";
    LimitLoadToSessionType =     (
        Aqua
    );
    ProgramArguments =     (
        "/Applications/mycompany.app/Contents/MacOS/Mycompany Module"
    );
    RunAtLoad = 1;
    Version = "200.200.200.200";
}

What am I missing here?

Replies

You seem to have hard coded user 501. Is that intentional?

If you create a second local user, do things work there? I suspect they won’t, and that test would rule out AD as a concern.

Share and Enjoy

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

Thanks for your response Quinn.

You seem to have hard coded user 501. Is that intentional?

I had written earlier code for an example. Below is how exactly the code looks like:

    logged_in_user=`users`
    
    for user in ${logged_in_user}; do
        user_uid=`id -u $user`

        launchctl enable gui/$user_uid/com.mycompany.client.myproduct
        echo "myproduct ui launchctl enable returns $?"

        echo "myproduct ui Launching UI for $user with uid: $user_uid "
        launchctl bootstrap gui/$user_uid /Library/LaunchAgents/com.mycompany.myproduct.plist
        echo "myproduct ui launchctl bootstrap returns $?"

    done

Yes it works for 2nd local user created. Even if I create a new user after installing my software with user1 (userid: 501), launchd successfully starts the agent for the user2 (userid: 502) which is created later. But it still doesnt work for the AD user (uid=1677024404)

So, lemme see if I have this straight:

  1. You have an Apple installer package (.pkg).

  2. It lays down a launchd agent property list in /Library/LaunchAgents.

  3. Its post-install script loads the agent in the current user’s GUI context with the launchctl bootstrap gui/UID PATH command.

  4. You log in to the Mac’s GUI using a local user account.

  5. And double click your package to open it in the Installer.

  6. You run through the installation process.

  7. At the end, the agent is running in the logged in user’s context.

  8. You uninstall your product.

  9. You repeat steps 4 through 6, but this time log in as an Active Directory user.

  10. At the end, the agent is not running in the logged in user’s context.

If you add a log point to your script inside your for loop, do you see the right value for user_uid? My weapon of choice for such logging is the logger man page tool.

Share and Enjoy

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

I list the steps and scenarios I am doing:

  1. I have an Apple installer package (.pkg).
  2. It lays down a launchd agent property list in /Library/LaunchAgents.
  3. Its post-install script loads the agent in the current user’s GUI context with the launchctl bootstrap gui/UID PATH command.
  4. I log in to the Mac’s GUI using a local user account.
  5. And double click your package to open it in the Installer.
  6. I run through the installation process.
  7. At the end, the agent is running in the logged in user’s context.
  8. I logout the current user and login to a different local user, I found that the agent is still running and listing in 'launchctl list' command.
  9. I logout the 2nd local user and login to an AD user, I found that the agent is not running and not listing in 'launchctl list' command.

Observation: Surprisingly if I install the .pkg using an AD user and switch to a local user or a different AD user I found the agent running and listing in 'launchctl list' command.

If you add a log point to your script inside your for loop, do you see the right value for user_uid?

The log is printing the local users ids . In my case there are two local users with user ids 501 and 502 and these two are printed in log when I login using a local user and install the pkg.

8. I logout the current user and login to a different local user, I found that the agent is still running and listing in 'launchctl list' command.

Still running? Or running again? Given that your agent is loaded into the Aqua session, I’d expect the first user’s agent to terminate when you log out and the system to start a new instance of the agent for the new user when you log in.

Please check that.

9. I logout the 2nd local user and login to an AD user, I found that the agent is not running and not listing in launchctl list command.

Well, that’s weird. I’ve got no good explanation for why that’d be the case.

Share and Enjoy

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

Still running? Or running again? Given that your agent is loaded into the Aqua session, I’d expect the first user’s agent to terminate when you log out and the system to start a new instance of the agent for the new user when you log in.

@eskimo you are right, i meant a new agent with a new pid is started when a new local user is logged in.

Well, that’s weird. I’ve got no good explanation for why that’d be the case.

@eskimo do you see any issue with the agent plist file I have loaded?

Also I wanted to know how is the launchd system is designed for launch agents? Since an AD user is not locally known, its userid will also be known in advance to the system. Then what is the need of enabling and bootstrapping an agent in a loop like below:

    for user in ${logged_in_user}; do
        user_uid=`id -u $user`
        launchctl enable gui/$user_uid/com.mycompany.client.myproduct
        launchctl bootstrap gui/$user_uid /Library/LaunchAgents/com.mycompany.myproduct.plist
    done

Another observation: If I add a new local user after installing the pkg (using 1st local user), the service is started when i switch to a newly created local user.

Also I wanted to know how is the launchd system is designed for launch agents?

A good place to start here is Technote 2083 Daemons and Agents. Some of the details have drifted, but the basic concepts still apply.

One of the details that has drifted is how launchd manages sessions. Figure 3 in TN2083 shows a separate instance of launchd for each user. That’s no longer the case. There’s a single instance of launchd per machine and it manages all the sessions.

When a session comes up, the system scans /Library/LaunchAgents for agents and loads any appropriate agents into that session. This is why you have that for … in loop. You’re forcing the agent to load into any existing GUI sessions, but if a new GUI session starts you expect the system to load your agent into the session based on its property list.

Share and Enjoy

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