tags:

views:

111

answers:

2

I'm writing an application that kicks off a subprocess running a simple web server. I am using NSTask and communicating with it with pipes, and everything seems more or less fine. However, if my program crashes, the subprocess is left alive and the next time I launch the app there is a conflict between the old subprocess and the new one. Is there any way to ensure that subprocesses die when the owning app dies?

+1  A: 

Your application delegate can implement the

- (void)applicationWillTerminate:(NSNotification *)aNotification

message, and terminate the NSTask there. However, it is not guaranteed that during a crash, this delegate will be called.

Two additional steps you can take:

  • Shutdown an existing, orphaned subprocess during the launch of a new parent-process by writing down to disk the PID of the subprocess on creation and removing it during normal shutdown (sometimes not the safest behavior).
  • Shutdown the subprocess if the NSPipe's end-point didn't send data for a specific amount of time (something like a heartbeat).
Aviad Ben Dov
A: 

UPDATE: Now that I go to check this properly it doesn't work. Trying to set the process group fails with this error;

EPERM "The effective user ID of the requested process is different from that of the caller and the process is not a descendant of the calling process."

There is a more recent thread on this issue but no easy solution as far as I can tell

http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html


I've tried a suggestion by Robert Pointon on Cocoadev in my app. I haven't got around to testing it yet though.

http://www.cocoadev.com/index.pl?NSTaskTermination

The idea is to set the process group of the task to be the same as that of the process that launches the task (note: the code below is basically lifted from the thread above).

    pid_t group = setsid();
    if (group == -1) {
        group = getpgrp();
    }

   [task launch]; 


if (setpgid([task processIdentifier], group) == -1) {
   NSLog(@"unable to put task into same group as self");
   [task terminate];
} else {
// handle running task
}
Ira Cooke