0

There are quite a few hints about how to keep programs alive, and restart them when they crash:

They all have one restriction in common, though: They all need to be run before the to-be-monitored program.

In my case, though, I have a faceless background app that has to decide on its own whether it wants to be restarted in case it crashes. So, my app would be launched first and cannot be quit to become a child of a monitoring process (for explanation see below).

I've tried the launchd solution by writing a plist file like this:

<?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.mydomain.myapp.restartAfterCrash</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/MyApp.app/Contents/MacOS/MyApp</string>
    </array>
</dict>
</plist>

It nearly does what I need, but in order to activate it from my app, by invoking it with launchctl load /path/to/file.plist, it wants to launch my app once more, so that my originally running app would have to quit to let the new instance run.

However, I cannot pass control to another instance of my app, because it's causing several new problems if the app was launched by double clicking a document the Finder or if it was launched by an AppleScript that wants to communicate further with my app. In those cases, my originally launched app must keep running, and thus the launchd method is not viable, nor is any other method that requires my app to run a new instance instead.

In short, are there other tested (reliable) methods that a Mac application can use to have itself restarted only if it crashes?

The only method I can think of is launching another faceless background application that monitors the first program's lifetime, e.g. via its PID.

I also wonder if it can be done with a simple shell command invocation that would periodically check whether my app is still alive, as those always run as a child process and would die along with the primary app, won't they?

Community
  • 1
  • 1
Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • Here's a method based on a parent/child app structure: http://stackoverflow.com/questions/22186070/monitoring-and-restarting-child-process-when-fails-exits – Phillip Mills Apr 28 '17 at 19:00
  • You might try `launchctl kickstart` instead of `launchctl load` (which is a legacy command anyway). `kickstart` has a `-k` option that kills a running service before restarting; that implies to me that *without* `-k`, no attempt is made to (re)start a running service. – chepner Apr 28 '17 at 19:09
  • @chepner I just updated my question to explain why it must not be restarted in order to be monitored. So I guess your suggestion won't work for my needs, either. – Thomas Tempelmann Apr 28 '17 at 19:11
  • @PhillipMills A parent/child relationship is exactly the kind I can't use as I explained, I thought, as my app would need to be the first one to be launched, i.e. it would be the parent. Or did I misunderstand the linked article? – Thomas Tempelmann Apr 28 '17 at 19:13
  • It's possible you misunderstood. There's one executable (your app) and, when it runs, it creates a child process that does the work. The parent does nothing but monitor the child and restart it via fork() when necessary. Essentially: one app, two pids. – Phillip Mills Apr 28 '17 at 19:17
  • With this approach, your app doesn't need to quit to become the child of some monitor. It is its own monitor. – Phillip Mills Apr 28 '17 at 19:19
  • @PhillipMills Nope, if my app (parent) crashes, its child would die with it and would not be able to restart my app again. – Thomas Tempelmann Apr 29 '17 at 07:54
  • Why would the parent crash? The only thing it's doing is watching the child. Someone might shut it down but...crash? – Phillip Mills Apr 29 '17 at 19:16

0 Answers0