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
I think I got it.
execl("/bin/sh", "sh", "-c", command, NULL);
runs sh
and popen2
returns it's pid. When you call kill
it kills sh
, but does not touch it's child process command
. It is actually a fluke that killing the next pid kills command
. 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):
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);
execvp(*command, command);
perror("execvp");
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;
}
and pass command in the form of
char *command[] = {"program", "arg1", "arg2", ..., NULL};
in your particular example:
char *command[] = {"crafty", NULL};
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:
pid_t popen2(char *command, int *in_fd, int *out_fd) {
int pin[2], pout[2];
pid_t pid;
char cmd[strlen(command)+10];
if (out_fd != NULL) {
if (pipe(pin) != 0) return(-1);
}
if (in_fd != NULL) {
if (pipe(pout) != 0) {
if (out_fd != NULL) {
close(pin[0]);
close(pin[1]);
}
return(-1);
}
}
pid = fork();
if (pid < 0) {
if (out_fd != NULL) {
close(pin[0]);
close(pin[1]);
}
if (in_fd != NULL) {
close(pout[0]);
close(pout[1]);
}
return pid;
}
if (pid==0) {
if (out_fd != NULL) {
close(pin[1]);
dup2(pin[0], 0);
}
if (in_fd != NULL) {
close(pout[0]);
dup2(pout[1], 1);
}
// Exec makes possible to kill this process
sprintf(cmd, "exec %s", command);
execlp("sh", "sh", "-c", cmd, NULL);
fprintf(stderr, "%s:%d: Exec failed in popen2. ", __FILE__, __LINE__);
perror("Error:");
exit(1);
}
if (in_fd != NULL) {
close(pout[1]);
*in_fd = pout[0];
}
if (out_fd != NULL) {
close(pin[0]);
*out_fd = pin[1];
}
return pid;
}