Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 any way to launch a task such that it terminates when your app terminates (even if it crashes)?

like image 930
Enchilada Avatar asked May 31 '11 22:05

Enchilada


3 Answers

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.

like image 84
user478681 Avatar answered Nov 15 '22 06:11

user478681


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.

like image 21
Jon Hess Avatar answered Nov 15 '22 06:11

Jon Hess


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
like image 45
Alex Gray Avatar answered Nov 15 '22 06:11

Alex Gray