-
Re: Different ways of launching a Cocoa app from the command line
eskimo Nov 10, 2016 1:30 AM (in response to aschweiz77)There are lots of differences, ranging from UNIXy stuff (
stdin
,stdout
,stderr
,environ
, current working directory, resource limits, and so on) to Mac-specific stuff (Mach bootstrap namespace, security context, and so on). There’s a somewhat outdated discussion of this in TN2083 but a) it’s certainly not comprehensive, and b) that’s not the main focus of that doc.My question is, why do you care? Users don’t run GUI apps from Terminal (or at least they shouldn’t), so you shouldn’t provide official support for that. And any mechanism you have in place for launching a GUI app should be launching it via high-level facilities (like NSWorkspace, which is what
open
uses) rather than low-level POSIX APIs.Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
Re: Different ways of launching a Cocoa app from the command line
alex.suzuki Nov 15, 2016 1:02 AM (in response to eskimo)Hi Quinn,
The reason we ask is because we are experiencing different behaviors when we launch an applicaiton as a Launch Agent via launchd.
If an application is invoked via /usr/bin/open, for instance with the plist below, it will open when lthe aunchctl load happens, and there are two processes around, the /usr/bin/open process and the calculator process. However, when launchctl unload happens, the /usr/bin/open process disappears but the process spawned by open remains. The application keeps running.
It can be easily reproduced for instance with the Calculator application:
Lauch Agent registration 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>Label</key> <string>com.classycode.calculator</string> <key>ProgramArguments</key> <array> <string>/usr/bin/open</string> <string>-W</string> <string>/Applications/Calculator.app</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> </dict> </plist>
Process output after launchctl load
$ ps aux | grep -i calculator ahs 5033 0.0 0.3 2659796 58500 ?? S 9:57AM 0:00.38 /Applications/Calculator.app/Contents/MacOS/Calculator ahs 5027 0.0 0.1 2547604 20484 ?? S 9:57AM 0:00.04 /usr/bin/open -W /Applications/Calculator.app
Process output after launchctl unload
$ ps aux | grep -i calculator ahs 5033 0.0 0.3 2658696 58460 ?? S 9:57AM 0:00.59 /Applications/Calculator.app/Contents/MacOS/Calculator
Regards
Alex
-
Re: Different ways of launching a Cocoa app from the command line
eskimo Nov 16, 2016 2:13 AM (in response to alex.suzuki)However, when launchctl unload happens, the /usr/bin/open process disappears but the process spawned by open remains.
Right. This is because, if a job is started when you unload it,
launchd
terminates it before the unload. This termination process uses UNIX signals, and it targets the process group assigned to the job. If you fork/exec from a launchd job, the child process ends up in the same process group as the parent (seekillpg
), and thus the child process gets terminated. OTOH, theopen
tool runs the app via NSWorkspace, which causes it to act just like it was launched by the user from Finder, which means it’s in a different process group, and thus doesn’t get terminated.Note Some of this is discussed in
launchd.plist
.It’s generally not a good idea to run a GUI app directly as a launchd agent. You would typically have the agent start the app and then have some other mechanism to terminate it. The best way to do that depends on your specific circumstances. Can you explain more about the big picture here?
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
Re: Different ways of launching a Cocoa app from the command line
alex.suzuki Nov 23, 2016 2:00 PM (in response to eskimo)"Hi Quinn,
Thank you for your answer, and pardon my late reply. That clarifies things a little.
I'm a bit confused about your comment about running a GUI app as launch agent being a bad idea. We are writing a GUI application for one of our clients that is supposed to run as soon as the user logs in, and should be always running. We can achieve this behavior by registering it as a launch agent. The application is mostly invisible (we display a menu bar icon to access its settings), and only pops up a window when a print job is processed by the CUPS printing system. The user can then associate some info with the job that was printed and the window disappears again. It's basically a local print acounting solution. We also take advantage of KeepAlive to automatically relaunch the application should a crash occur.
Are there any guides, patterns or best practices on achieving this kind of behavior? Or to ask more bluntly, what is wrong with the way we do things now? Unfortunately the "Designing Daemons and Services" guide does not provide much insight here, only mentioning that "They (agents) can display a visual interface, but this is not recommended.".
-
Re: Different ways of launching a Cocoa app from the command line
eskimo Nov 24, 2016 12:38 AM (in response to alex.suzuki)I’ve just noticed that there are two folks on this thread; are you and aschweiz77 working on the same project?
The application is mostly invisible (we display a menu bar icon to access its settings), and only pops up a window when a print job is processed by the CUPS printing system.
We’re suffering from terminological confusion here. When aschweiz77 started this thread they wrote Cocoa app and then you followed up with Calculator as an example, leading me to believe that you were working on a standard GUI app, one with an icon in the Dock and a menu bar. This does not work well as a launchd agent because the user expects to be able to quit the app, and they’ll be kinda peeved when launchd merrily relaunches it for them.
What you’re creating is commonly known as a UI element; these generally work out OK as a launchd agent.
However, I wonder if you could do better. Right now you have a complete GUI app permanently running in the background, even if the user never prints for the entire login session. Wouldn’t it be better to monitor the printing system with a lightweight launchd agent and then, when there is UI work to be done, launch your UI element to do that work?
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
Re: Different ways of launching a Cocoa app from the command line
alex.suzuki Nov 24, 2016 1:06 AM (in response to eskimo)Hi Quinn,
Yeah, we are working on the same project.
Good to hear that our approach is not completely wrong for what we are building. We could go down the route you describe, but the app also offers some functionality through the menu bar icon, like a list of past print jobs, and browser links to the client's web platform, which the client wants to be always present.
Kind Regards
Alex
-
-
-
-
-