Why does telling an app to quit sometimes leave a zombie, and how can I kill it

applescriptdocklaunchd

I have two scripts that open and close an app; let's say it's the builtin Calculator.app. The "start" script uses /usr/bin/open to launch the app, then a one-line AppleScript to set the app's visibility to false.
This is the entirety of the "stop" script:

#!/bin/bash

osascript -e 'tell app "Calculator" to quit'

I am running these scripts from a LaunchDaemon that calls them at certain fixed times of the week.

The strange behavior I'm seeing is that sometimes, after the "stop" script runs, the app's Dock icon retains its little dot (suggesting it's still running). However:

  • right-clicking the Dock icon shows "Application not responding"
  • force-quitting via the Dock icon's menu does nothing
  • ps does not show any Calculator process running

And, most bafflingly, trying to launch Calculator again (via open, via Spotlight, or by double-clicking its icon) produces a modal dialog that says The application "Calculator" is not open anymore.

lsof shows these entries that might be related:

COMMAND     PID   USER   FD     TYPE             DEVICE   SIZE/OFF     NODE NAME
Spotlight   443 jteach   54r     DIR                1,4        102 28977573 /Applications/Calculator.app
Notificat   476 jteach  txt      REG                1,4      37933 29214948 /System/Library/Frameworks/NotificationCenter.framework/PlugIns/com.apple.ncplugin.calculator.appex/Contents/Resources/Assets.car
Notificat   476 jteach    8r     REG                1,4      37933 29214948 /System/Library/Frameworks/NotificationCenter.framework/PlugIns/com.apple.ncplugin.calculator.appex/Contents/Resources/Assets.car

My questions:

  • Why might my "stop" script be failing to make the app exit cleanly?
  • Short of rebooting, is there a way I can get the app out of this zombie state?
  • How can I alter my script to be sure that the app quits properly?

Best Answer

It seems like you have found a solution to your problem, but in case others are looking for more tools for their Unix-y toolbelt, here are a few:

quit

I have kept Jon Stovell’s shell script quit (direct download link) around for several years now, and it seems to do a very good job of quitting apps. It tries a variety of methods, and will try to allow an app to ”save changes” if necessary.

appswitch

Another very useful tool is Nicholas Riley’s appswitch (GitHub page) which will let you do a whole slew of things to apps, including quitting them (or hiding them, or showing their windows but not making them active, etc).

pkill

killall has already been mentioned, but I’d be remiss if I didn’t add that you could also use:

pkill -x Calculator

to get rid of the pesky app. I haven’t seen “dock zombies” so I can’t so whether or not that would fix the problem, but if it does, it might be preferable to two sudo commands.

A note about open

You mentioned that you are launching the app with open and then using AppleScript to hide it. Well-behaved apps should be respond to the -j flag to open to accomplish this without AppleScript, i.e.:

open -j -a Calculator

(see man open for details, such as "-j Launches the app hidden"; not to be confused with -g which means "Do not bring the application to the foreground." I can never remember which is which so I almost always use open -g -j -a Foo whenever I want to launch an app but not have it steal focus.)