C: Exec/fork > Defunct processes
Asked Answered
A

2

15

I'm want to create a lot of child processes using the fork > exec procedure. Many processes are ending very fast (in less than two minutes, some even earlier).

My first problem is, I put the spawn process into the background with

./spawnbot > logging.txt
[CTRL+Z]
bg 1
disown

So far so good. Now I don't see any of the spawnbot's messages anymore and they go straight into the logging.txt. However, whenever a new child is created I see all the info about that child in my console again.. I now wanted to start each child with it's own pipe - is there a better way to not have children post their output messages all over the console? Should I just redirect it to /dev/null or is this done with some flag in C?

Secondly, all the children don't really get killed. I have a lot of processes in my ps -ef. What can I do about that? How do I d

Ammonic answered 16/7, 2011 at 15:16 Comment(0)
J
23

First your second question!

Your children stay in 'zombie' mode because the kernel thinks you might still want to retrieve a return value from them..

If you have no intention to get return values from your child processes, you should set the SIGCHLD signal handler in the parent process to SIG_IGN to have the kernel automatically reap your children.

signal(SIGCHLD, SIG_IGN);

The first question depends a it on your implementation..

But general speaking, just after you fork() you should use close() to close the old file descriptors for 0 and 1 and then use dup2() to set them to your wanted values.. No time for an example right now, but hope this pushes you in the right direction..

Jefferey answered 16/7, 2011 at 16:31 Comment(1)
An interesting quotation from "The Linux Programming Interface": "Note that even though the default disposition for SIGCHLD is to be ignored, explicitly setting the disposition to SIG_IGN causes the different behavior described here. In this respect, SIGCHLD is treated uniquely among signals."Untoward
C
18

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
Cyclograph answered 16/7, 2011 at 17:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.