Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

10.5: Automatically restart a crashed program System 10.5
This older hint described a method by which to auto-restart a crashed application automatically by monitoring the crash log for the app. This was done by watching the log file with a LaunchAgent.

As WCityMike notes in this forum thread, Leopard writes multiple crash logs with a date and time-stamp in the filename for each crash, rather than appending to one log file as in Tiger. For example:
~/Library/Logs/CrashReporter/gimp-2.2_2007-12-10-100248_G4.crash
~/Library/Logs/CrashReporter/gimp-2.2_2007-12-10-091933_G4.crash
etc...
So watching a single file will not work in Leopard. Read on for my solution.

I wanted to keep true to the original tip and use Lingon to create the LaunchAgent (launchd) plist file, and only use that rather than creating a second file containing the script to be called by the LaunchAgent, which does the actual work of watching the files. However, Lingon for Leopard scrambles the plist with the commands needed -- it sees every space in the command as a newline, and also kills single quotes. So I made the plist using a plain text editor:
<?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>Resuscitation</string>
	<key>Program</key>
	<string>/usr/bin/osascript</string>
	<key>ProgramArguments</key>
	<array>
		<string>osascript</string>
		<string>-e</string>
		<string>set lib to (path to library folder from user domain) &amp; "Logs:CrashReporter:" as text</string>
		<string>-e</string>
		<string>set appLogName to "yourLogname"</string>
		<string>-e</string>
		<string>tell application "Finder"</string>
		<string>-e</string>
		<string>set t to files of alias lib whose modification date is greater than ((get current date) - 2* minutes)</string>
		<string>-e</string>
		<string>try</string>
		<string>-e</string>
		<string>set t to item 1 of (sort t by modification date)</string>
		<string>-e</string>
		<string>end try</string>
		<string>-e</string>
		<string>end tell</string>
		<string>-e</string>
		<string>if t is not {} then</string>
		<string>-e</string>
		<string>tell application "Finder"</string>
		<string>-e</string>
		<string>if name of (t as alias) contains appLogName then</string>
		<string>-e</string>
		<string>tell application "yourappname" to activate</string>
		<string>-e</string>
		<string>end if</string>
		<string>-e</string>
		<string>end tell</string>
		<string>-e</string>
		<string>end if</string>
	</array>
	<key>WatchPaths</key>
	<array>
		<string>/Users/USERNAME/Library/Logs/CrashReporter</string>
	</array>
</dict>
</plist>
How to Build

Open a new Textedit document, and make it plain text if it is not already. Paste the above xml code into it. Replace the word yourLogname in the line <string>set appLogName to "yourLogname"</string>. The log file name should start with the app's name; my log files look like this: gimp-2.2_2007-12-10-100248_G4.crash -- so I use the text before the hyphen (ie I used gimp for my app name).

Replace the word yourappname in the line <string>tell application "yourappname" to activate</string> with your app's name. My app is called gimp, so I replace "yourappname" with "gimp".

Finally, replace the word USERNAME with your short user name in the <string>/Users/USERNAME... line. If my user name is John Smith, then normally my short username will be jsmith -- your home folder is normally named as your short user name. Save the file somewhere with the extension .plist (not .txt!). From here on, I will refer to this file as foo.plist.

Where to Place

I have used the LaunchAgents folder in the top-level /Library folder. This LaunchAgents folder is for all users rather than just me. You can use your Users one instead, but I have not tested this hint with that folder. Drag and drop the file into the folder /Library/LaunchAgents; you will be asked to authenticate as it is a protected folder, so do so using your Admin password.

Now some Terminal work is required. The plist files in the folder /Library/LaunchAgents are owned by system, so we need to set our file to the same owner. In Terminal, type this command, replacing foo.plist with your file's name:
sudo chown root: /Library/LaunchAgents/foo.plist
You will be asked to authenticate, so do so using your Admin password. Now load the LaunchAgent by typing this command, again replacing foo.plist with your file's name:
launchctl load /Library/LaunchAgents/foo.plist
If you do not want to load the LaunchAgent this way, then you can do so by logging out and back in again.

Notes:

A couple of things about the commands in the plist file. I used osascript, which allows AppleScript to be used from the command line. I chose osascript because I found that using unix shell commands to look for the new crash log file sometimes actually triggered the LaunchAgent. Also I found it easier. :-)

The LaunchAgent now looks at a folder rather than a file; this is called a watchPath. This means that if a file is moved in or out of this watchPath (folder), then the LaunchAgent will trigger. This can be a problem when a crash report file for another app is created. Or as I suspect will happen, the system tidies up the CrashReporter folder and removes files. However, the osascript in the LaunchAgent takes this into account and only reopens your application if the log file contains your app name and the file's modification date is in the last two minutes.

To uninstall the LaunchAgent, remove it from the LaunchAgents folder, and log out and back in. To just unload it, use Terminal and type:
launchctl unload /Library/LaunchAgents/foo.plist
Do not open/edit this file in Lingon; Lingon will scramble the file. I have tested this as much as I can, and it works for me.
    •    
  • Currently 2.17 / 5
  You rated: 4 / 5 (6 votes cast)
 
[10,903 views]  

10.5: Automatically restart a crashed program | 10 comments | Create New Account
Click here to return to the '10.5: Automatically restart a crashed program' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
10.5: Automatically restart a crashed program
Authored by: darick on Dec 19, '07 08:16:21AM

I found it quite convenient to watch a hidden file in the same folder that seems to keep track of the crash history. It appears to update each time that the crash log is updated, but I can't exactly be sure.
Using Quicksilver as an example, I am watching: ~/Library/Logs/CrashReporter/.Quicksilver_rbt_CrashHistory.plist

I would appreciate any additional information on the subject. Thanks for the post.



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: statistics on Dec 19, '07 07:38:38PM

Somebody give darick a prize! Much simpler than this new hint is to use the old hint with these hidden files.



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: mark hunte on Dec 20, '07 02:44:07AM

I agree,
looks like Apple have hidden a plist file for each app with a crash log to tell some part of the system the date and path for each apps last log file with a dated name.
I see no reason these should not work with the old hint.
Good catch Darick.

If not necessary for the log files, My hint will have its uses where similar checking on 'name contains' is needed with LaunchAgents. :-)



---
mh



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: macavenger on Dec 19, '07 09:10:55AM

If you are going to be using a LaunchAgent anyway, why not just set up the launchAgent to run the app? That is, after all what it is designed to do-launch an application/script/etc and keep it running, restarting it if it crashes. Works quite nicely, and Lingon makes it easy to set up. There is even a flag you can set to say "Only relaunch this application if it crashes, not if it exits cleanly", so you can still exit out of the application manually if you want. If you didn't want the application to open immediately on login, it would probably still be easier and cleaner to simply write a basic script to load/unload the LaunchAgent when desired, rather than writing a complicated script to watch files.

---
Aluminum iMac 20" 2.4 GHz/3GB/300GB HD



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: mark hunte on Dec 19, '07 11:33:28AM

This hint is for when the app crashes nor when you quit. Keep always running is not the aim.

Show me where you see 'Only when it crashes', Because in Lingon for Leopard there is no such options AFAICS

---
mh



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: macavenger on Dec 19, '07 01:48:20PM
This hint is for when the app crashes nor when you quit. Keep always running is not the aim.
As I noted in my comment, you can do this through launchd
Show me where you see 'Only when it crashes', Because in Lingon for Leopard there is no such options AFAICS
from the launchd.plist man page (which has all the configuration options you can put into a LaunchAgent or LaunchDaemon plist file):
KeepAlive [boolean or dictionary of stuff]
This optional key is used to control whether your job is to be kept continuously running or to let demand and conditions control the invocation.
[...SNIP...]

    SuccessfulExit [boolean]
    If true, the job will be restarted as long as the program exits and with an exit status of zero. If false, the job will be restarted in the inverse condition.
It looks like Lingon may not have this key easily available, but it most certainly is an option through launchd.

---
Aluminum iMac 20" 2.4 GHz/3GB/300GB HD

[ Reply to This | # ]

10.5: Automatically restart a crashed program
Authored by: macavenger on Dec 19, '07 02:00:36PM
Show me where you see 'Only when it crashes', Because in Lingon for Leopard there is no such options AFAICS
Ok, yeah. The newest version of Lingon apparently doesn't have this option. Actually, the latest version is a bit of a step back from the older ones I've used in terms of flexibility and power. In the previous version you could put multi-line commands in on the main screen, and it had a custom editor as well if you wanted to edit the .plist directly. The current version is easier to use for basic stuff, but not as good for advanced stuff. Unless, of course, I am missing something, in which case please correct me :) So yeah, you would need to edit the .plist file directly to add this key.

---
Aluminum iMac 20" 2.4 GHz/3GB/300GB HD

[ Reply to This | # ]

10.5: Automatically restart a crashed program
Authored by: mark hunte on Dec 19, '07 05:33:17PM

Now I am not going to even suggest I am an expert,
SuccessfulExit sound like what we are looking for, but Does it work.
I have tried the SuccessfulExit key true and false, with and without KeepAlive true. It does not work
So please show us how you would do it, ( keeping the app running when it crashes but letting it stay quit when you quit it.)

---
mh



[ Reply to This | # ]
10.5: Automatically restart a crashed program
Authored by: macavenger on Dec 20, '07 09:38:54AM
I have tried the SuccessfulExit key true and false, with and without KeepAlive true. It does not work So please show us how you would do it, ( keeping the app running when it crashes but letting it stay quit when you quit it.)
The key here is that KeepAlive can be either a bool OR a dict- in this case we need it to be a dict, with the SuccessfulExit key as a child bool set to false. So, using my company's flight management software as an example, you would end up with the following LaunchAgent .plist file (I put it in my home library/LaunchAgents folder):
<?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>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>com.frontierflying.flightmaster</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Users/Shared/FlightMasterStandalone/FlightMaster2004.app/Contents/MacOS/EXE</string>
	</array>
</dict>
</plist>
I made the inital file using Lingon, and then simply edited it to add the KeepAlive dict/key set. The program arguments string needs to be the path to the actual executable inside the app bundle, not just to the .app (assuming it is a bundle app) as shown.

Of course, this loads immediately at login. If this is the desired behavior, then you are done. If you don't want this, then put the .plist file in your documents directory or something, and use something like the following two line script to load it as desired:

launchctl unload /path/to/launchagent.plist
launchctl load /path/to/launchagent.plst
The unload command is needed only if you want to launch the application multiple times in a session. From what I can tell, once loaded the LaunchAgent remains loaded, and simply stops monitoring the app after it quits cleanly- but doesn't unload. In order to relaunch the app, you first have to unload the LaunchAgent, the load it again, thus the first line of the script. That script should be able to be put into an apple script using the "do shell script" apple script command if you want (although I didn't test this), or just leave it as a terminal script. Then just run that script, and launchd will launch your application, monitor it, and restart it if it crashes, but not if it exits cleanly. Perhaps in the end this isn't all that much simpler than your method, but it feels cleaner to me.

---
Aluminum iMac 20" 2.4 GHz/3GB/300GB HD

[ Reply to This | # ]

10.5: Automatically restart a crashed program
Authored by: mark hunte on Dec 20, '07 12:50:54PM

Thanks for explaining all that macavenger, I will check it out.

---
mh



[ Reply to This | # ]