Launch daemons and keeping applications open.

neilrooney
New Contributor II
Hi everyone, wondering if I could get some help with launch daemons. 
  • I have an app that runs on reboot and cannot be disabled. (Feature not included in managed preferences)
  • Goal is to ensure the app is kept alive when quit by an end user.
  • Launch daemon was my first thought.
  • Works well until reboot when two instances of the app are opened.
How can I have launchd not open the second instance of the app on reboot and only when the user quits once logged in?
 
<?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>Disabled</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.cloudflare.warp.lc</string>
<key>Program</key>
<string>/Applications/Cloudflare WARP.app/Contents/MacOS/Cloudflare WARP</string>
</dict>
</plist>
3 REPLIES 3

mm2270
Legendary Contributor III

Hmm. I wonder. You might try adding a LimitLoadToSessionType key to the launchd. 

 

<key>LimitLoadToSessionType</key>
<string>Aqua</string>

 

If I'm not mistaken, that should tell the LaunchDaemon to only run when someone is logged in, that way it won't try to open the application during the restart process, but only once login has occurred.

This is just a guess. I haven't actually seen an instance of a LaunchDaemon causing an app to open twice like that myself. Hopefully adding that key to your launchd will address it.

neilrooney
New Contributor II

@mm2270 thanks so much for jumping in and offering help. 

So I made the change you recommended and sadly no dice. Two instances of the app are opened on reboot. Of course the fix would be to have the app not open on boot and have the launchd manage it, but once the app is managed via preferences in Jamf, we cannot disable it from starting automatically. A failure of the vendor. 

I had hoped launchd had a way to see an instance was already open and not open another. 

mjhersh
Contributor
Do you know what mechanism Cloudflare uses to run on startup? Does it use its own LaunchAgent or LaunchDaemon? Does it add it to System Preferences > Users > Login Items? If it's either of those, you could disable it via script. If it's something sneakier like a system extension that's needed for other functionality, then perhaps not.
 
While the ability to scan for running processes isn't built in to LaunchAgents/LaunchDaemons, you can add your own additional logic by writing a custom script and then running that script from your agent/daemon instead of running the target program directly.
 
Here's a quick example script you could try (untested, but should work in principle). Save it somewhere accessible and set appropriate permissions (e.g. `sudo chown root:admin /path/to/script; sudo chmod 755 /path/to/script`)
 

 

 

#!/bin/sh

# find running instances of Cloudflare using grep
ps ax | grep -v grep | grep "/Applications/Cloudflare WARP.app"

# if grep finds no matches it will return an error code (> 0)
if [ $? -gt 0 ]; then
    "/Applications/Cloudflare WARP.app/Contents/MacOS/Cloudflare WARP"
fi

 

 

 
 
One possible gotcha is that there might be a race condition here. If this agent/daemon runs *before* the built-in autostart kicks in, you might still wind up with two copies running immediately on login. You might want to implement a "sleep 5" command at the beginning or something like that to give the built-in method some time to do its thing.
 
Also, since this appears to be a GUI app, I think it would make more sense to run as a a LaunchAgent rather than as a LaunchDaemon. Agents run as the user after login, while daemons run as root immediately on startup (even if no user is logged in). I'm not sure how Cloudflare Warp works though, so I might be wrong about which one is appropriate. 
 
Edit: also, if running in userspace, it might be better to run `open "/Applications/Cloudflare WARP.app`. Using the open command works just like double-clicking the app in the Finder, so it will NOT launch a second copy if it's already running. One thing to keep in mind is that by default, `open` exits immediately, so if you have the script set to "keepalive" it will constantly run, exit, and restart. In that case you'd want to throw in some sleep commands for sure (and maybe also a loop?) so it doesn't eat all your CPU time.