Reputation: 459
Some days ago, I asked here how to start a program using C without using fork(). This solution is working fine.....except that I can't kill this child process! My program (in this case, 'rbfeeder') has some threads....and when I send kill signal, only threads are killed (I think). What am I doing wrong?
This is the code used to 'start' rbfeeder:
/*
* Start dump1090, if not running
*/
void startDump(void) {
if (p_dump != 0) {
log_level(8, "Looks like dump is already running.\n");
return;
}
pid_t ret = run_cmd("/home/jmaurin/dev/client/rbfeeder");
if (ret != 0) {
log_level(8, "Ok, started! Pid is: %i\n", ret);
p_dump = ret;
sendStats();
} else {
log_level(8, "Error starting dump1090\n");
p_dump = 0;
sendStats();
}
return;
}
And this is the code to 'stop':
void stopDump(void) {
if (checkDumpRunning()) {
log_level(3, "Dump is running, let's try to kill.\n");
if (kill(p_dump, SIGKILL) == 0) {
log_level(3,"Succesfull kill dump!\n");
sendStats();
return;
} else {
log_level(3,"Error killing dump.\n");
return;
}
} else {
log_level(3, "Dump is not running.\n");
}
return;
}
and run_cmd function:
pid_t run_cmd(char *cmd) {
pid_t pid, ret;
char *argv[] = {"sh", "-c", cmd, NULL};
int status, s;
posix_spawn_file_actions_t file_actions;
posix_spawn_file_actions_t *file_actionsp;
s = posix_spawn_file_actions_init(&file_actions);
if (s != 0)
return 0;
//STDERR_FILENO
s = posix_spawn_file_actions_addclose(&file_actions,STDERR_FILENO);
if (s != 0)
return 0;
file_actionsp = &file_actions;
//printf("Run command: %s\n", cmd);
status = posix_spawn(&pid, "/bin/sh", file_actionsp, NULL, argv, environ);
if (status == 0) {
log_level(8, "Child pid: %i\n", pid);
ret = pid;
/*
if (waitpid(pid, &status, 0) != -1) {
printf("Child exited with status %i\n", status);
} else {
perror("waitpid");
}
*/
} else {
// printf("posix_spawn: %s\n", strerror(status));
ret = 0;
}
return ret;
//printf("End of run\n");
}
p_dump is a global variable to hold PID.
This image is when my 'client' receive the command (over ethernet) to start external program:
Then, an HTOP on the same machine....see that PID are the same, which means that my variable is correct:
Then, I've sent an 'stop' command and my client executed 'stopDump', but one process still running (the other threads from same program are 'killed'):
The external program doesn't 'spawn/fork' itself, but it does have threads.
Upvotes: 2
Views: 1937
Reputation: 459
The answer by user1937198 worked fine, but I found another way that doesn't need to call any function, like 'waitpid'.
struct sigaction sigchld_action = {
.sa_handler = SIG_DFL,
.sa_flags = SA_NOCLDWAIT
};
sigaction(SIGCHLD, &sigchld_action, NULL);
At least in my case, it's preventing zombie proccess after kill. It's works fine.
Upvotes: 1
Reputation: 5366
Your kill is completing successfully, because the process is becoming a zombie, (The Z in the status column in HTOP). A zombie is a process that still has metadata in the kernel, but is not actually running. To get rid of the zombie, the parent has to wait on the process. As your process is the parent, adding a call to waitpid(p_dump)
after the kill succeeds should handle this.
Upvotes: 3