I'm using the function popen2 (that has been recommended elsewhere on stackoverflow) to programatically create a process that has to be killed again after some time. popen2 returns a PID and I thought that this PID could be used to kill the process. It doesn't work this way, though. In order to kill it, I have to increment the returned PID, which I don't understand (see code below)
Another problem might arise when various threads are doing this in parallel. In that case the PIDs might differ by more than one due to race conditions, I think.
So my question is this: How can I reliably identify the PID of the process created by popen2 in a multi-threaded scenario?
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#define READ 0
#define WRITE 1
pid_t popen2(const char *command, int *infp, int *outfp) {
int p_stdin[2], p_stdout[2];
pid_t pid;
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
return -1;
pid = fork();
if (pid < 0)
return pid;
else if (pid == 0)
{
close(p_stdin[WRITE]);
dup2(p_stdin[READ], READ);
close(p_stdout[READ]);
dup2(p_stdout[WRITE], WRITE);
execl("/bin/sh", "sh", "-c", command, NULL);
perror("execl");
exit(1);
}
if (infp == NULL)
close(p_stdin[WRITE]);
else
*infp = p_stdin[WRITE];
if (outfp == NULL)
close(p_stdout[READ]);
else
*outfp = p_stdout[READ];
return pid;
}
main() {
pid_t pid;
// Create process
pid = popen2("crafty", &in, &out);
sleep(5);
// Why doesn't kill(pid, SIGKILL) work?
kill(pid+1, SIGKILL);
while (1);
}
I think I got it.
runs
sh
andpopen2
returns it's pid. When you callkill
it killssh
, but does not touch it's child processcommand
. It is actually a fluke that killing the next pid killscommand
. This will not always work and is just up to race conditions.If you want to be able to kill your target process then you will have to start that directly.
Warning (untested code):
and pass command in the form of
in your particular example:
You can use 'exec' command of shell to avoid pending process. Also: popen2 shall close the writing end of unused pipes, otherwise the pipe remains open. If one of pointers (infp, outpf) is NULL, it is useless to create and immediately close the pipe. Here is the version of popen2 I use in my project: