Terminate an NSTask and its children
Asked Answered
N

1

5

I'm using NSTask to execute a series of long running commands like so:

commandToRun = @"command 1;command2";
NSArray *arguments = [NSArray arrayWithObjects:
                      @"-c",
                      commandToRun,
                      nil];
self.task = [[NSTask alloc] init];
[self.task setLaunchPath: @"/bin/sh"];
[self.task setArguments: arguments];
[self.task launch];

This creates a process for the shell, and a child process for whichever command is running at the time (command 1 or command 2). If I kill the task with [self.task terminate] it only kills the parent process. Is there a way to identify and kill the children too?

Nidianidicolous answered 11/12, 2013 at 14:30 Comment(2)
According to the documentation terminate sends SIGTERM to the subtasks. Are you sure your subtasks can listen for SIGTERM?Zubkoff
A solution that doesn't involve the shell would be to create an NSTask for each process. If they're meant to be chained, (a) your current code won't do that and (b) with two NSTasks, you can launch the second one from the terminationHandler of the first.Doubleheader
N
4

It's not exactly elegant, but you can make sh launch the subtasks as background processes and then write their PIDs to a file using the shell variable $! as per here, blocking till each background process completes to maintain asynchronicity:

commandToRun = @"command1 & echo $! > /tmp/childpid; wait $!; command2 & echo $! > /tmp/childpid; wait $!";

Then when you call [self.task terminate] you should also invoke:

system("kill -9 `cat /tmp/childpid`");
...or something equivalent.
Neutralization answered 11/12, 2013 at 16:5 Comment(1)
That'll work. It's actually not as horrific as I what I was thinking I was going to have to do. Thanks!Nidianidicolous

© 2022 - 2024 — McMap. All rights reserved.