I am using waitpid(2) to check and mark the status of my processes of my job control program. I am using the WUNTRACED option, to catch useful signal like SIGTSTP in a job control program.
The problem is, when CTRL-Z (SIGTSTP) my program, the PID returned by waitpid(2) is correct (>0), but when killing it with a CTRL-C (SIGINT), the PID returned is -1. How is that ? How can I mark the status of my process then ? Since it return an invalid PID and set errno to ECHILD.
#include <sys/types.h>
#include <stdbool.h>
#include <termios.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main(void)
{
pid_t pid;
pid_t ret;
int stat_loc;
if ((!(pid = fork())))
{
execve("/bin/ls", (char *const []){"ls", "-Rl", "/", NULL}, NULL);
}
else if (pid > 0)
{
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
ret = waitpid(-1, &stat_loc, WUNTRACED);
printf("\nwaitpid returned %d\n", ret);
}
return (0);
}
EDIT: Problem solved, see the trick with SIGCHLD when you ignore it.
You're ignoring SIGCHLD
:
signal(SIGCHLD, SIG_IGN);
Status information for a process shall be generated (made available to the parent process) when the process stops, continues, or terminates except in the following case:
- If the parent process sets the action for the
SIGCHLD
signal toSIG_IGN
, or if the parent sets theSA_NOCLDWAIT
flag for theSIGCHLD
signal action, process termination shall not generate new status information but shall cause any existing status information for the process to be discarded.
If you want to wait()
on a child process, you can't ignore SIGCHLD
.