Reputation: 9480
I have this c code
/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
/* Wait for all dead processes.
* We use a non-blocking call to be sure this signal handler will not
* block if a child was cleaned up in another part of the program. */
//printf("Inside handler: \n");
while (waitpid(-1, NULL, WNOHANG) > 0) {
printf("reaped\n");
}
//printf("Outside handler: \n");
}
int main (int argc, char *argv[])
{
struct sigaction act;
int i;
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
/* Make some children. */
for (i = 0; i < 5; i++) {
switch (fork()) {
case -1:
perror ("fork");
return 1;
case 0:
exit(0);
return 0;
default:
//printf("inside parent\n");
printf("Created child %d\n", i);
}
}
/* Wait until we get a sleep() call that is not interrupted by a signal. */
while (sleep(1)) {
printf("inside parent while loop\n");
}
return 0;
}
I am calling fork 5 times, so I expect total 5 child process and 1 parent process. When I run this code, I get this output
Created child 0
Created child 1
reaped
reaped
Created child 2
Created child 3
Created child 3
reaped
reaped
Created child 4
reaped
inside parent while loop
I can't quite figure out why I am seeing child3 twice. There should not be any duplication with regards to i as i is incrementing in every iteration.
Can somebody explain why I am seeing child3 twice?
Upvotes: 1
Views: 59
Reputation:
The state of the stdio buffers is contained in the process's memory space. If the buffers are not empty at the time of a fork, the parent and child both have a copy of the information that says "Child process 3\n"
is in the stdout buffer, waiting to be flushed.
And they will both eventually flush it.
You can avoid this by calling _exit
instead of exit
in the child process. exit
is usually a bad idea when you're in a process that has not completed a successful exec since it was created.
Upvotes: 1
Reputation: 17872
The problem is your debugging output. It's undefined behavior to call printf in your async signal handler. There's only a short list of functions guaranteed to be safe during a signal handler.
If you remove it, you'll see the one outside of the signal handler never has unexpected behavior.
Upvotes: 0