开发者

Terminate NSTask even if app crashes

If my app crashes I don't get a chance to terminate the NSTasks it spawned, so they stay around eating up resources.

Is there an开发者_Go百科y way to launch a task such that it terminates when your app terminates (even if it crashes)?


I suppose you need to handle application crashes manually and in a different way to terminate spawned processes. For example, you can check following article http://cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html and in exception/signal handler when the application crashes send terminate signal to your child processes using kill(pid, SIGKILL), but for this you need also to keep the pid of child processes (NSTask - (int)processIdentifier) somewhere to get it from exception/signal handler.


What I've done in the past is create a pipe in the parent process, and pass the write end of that pipe into the child. The parent never closes the read end, and the child watches the write end to close. If the write end ever closes, that means the parent exited. You'll also need to mark parent's end of the pipe to close on exec.


I actually wrote a program / script / whatever that does just this… Here's the shell script that was the foundation of it… The project actually implements it within X-code as a single file executable.. weird that apple makes this so precarious, IMO.

#!/bin/bash
echo "arg1 is the SubProcess: $1, arg2 is sleepytime: $2, and arg3 is ParentPID, aka $$: $3"
CHILD=$1 && SLEEPYTIME=$2 || SLEEPYTIME=10; PARENTPID=$3 || PARENTPID=$$

GoSubProcess () {                      # define functions, start script at very end.
 $1 arguments &                         # "&" puts SubP in background subshell
 CHILDPID=$!                            # what all the fuss is about.
 if kill -0 $CHILDPID; then             # rock the cradle to make sure it aint dead
     echo "Child is alive at $!"        # glory be to god
 else echo "couldnt start child.  dying."; exit 2; fi
 babyRISEfromtheGRAVE # keep an eye on child process
}
babyRISEfromtheGRAVE () {
echo "PARENT is $PARENTPID";            # remember where you came from, like j.lo
while kill -0 $PARENTPID; do            # is that fount of life, nstask parent alive?
    echo "Parent is alive, $PARENTPID is it's PID"
    sleep $SLEEPTIME                    # you lazy boozehound
    if kill -0 $CHILDPID; then      # check on baby.
        echo "Child is $CHILDPID and is alive."
        sleep $SLEEPTIME                # naptime!
    else echo "Baby, pid $CHILDPID died!  Respawn!"
        GoSubProcess; fi                # restart daemon if it dies
done                                    # if this while loop ends, the parent PID crashed.
logger "My Parent Process, aka $PARENTPID died!"
logger "I'm killing my baby, $CHILDPID, and myself."
kill -9 $CHILDPID; exit 1               # process table cleaned.  nothing is left.  all three tasks are dead.  long live nstask.
}
GoSubProcess                # this is where we start the script.
exit 0                      # this is where we never get to


You could have your tasks periodically check to see if their parent process still exists.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜