Your child processes are getting killed. Defunct processes are also called zombie processes; zombies are dead! A zombie process is nothing but an entry in the process table, it doesn't have any code or memory.
When a process dies (by calling _exit
, or killed by a signal), it must be reaped by its parent. Every resource used by the process other than the entry in the process table disappears. The parent must call wait
or waitpid
. Once the parent has been notified of the child process's death, and has had the opportunity to read the child's exit status, the child's entry in the process table disappears as well: the zombie is reaped.
If you never want to be notified of your children's death, ignore the SIGCHLD
signal; this tells the kernel that you're not interested in knowing the fate of your children and the zombie will be reaped automatically.
signal(SIGCHLD, SIG_IGN)
If you only want to be notified of your children's deaths in specific circumstances, call sigaction
with the SA_NOCLDWAIT
flag. When a child dies, if the parent is executing one of the wait
family of functions, it'll be notified of the child's death and be told the exit status; otherwise the child's exit status will be discarded.
struct sigaction sa;
sa.sa_handler = &my_sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, NULL);
Regarding the output, your children write to the same places as the parent unless you've explicitly redirected them (with close
and open
, or dup
, or a number of other possibilities). Your children are probably printing diagnostic messages to standard error (that's what it's for, after all).
./spawnbot >logging.txt 2>&1
In addition, since you seem to want to detach the children from the terminal, you probably want to make sure they don't receive a SIGHUP if you kill the terminal. So use nohup
:
nohup ./spawnbot >logging.txt 2>&1 &
disown