I'm trying to understand how the waitpid() call works. I've written
the following code which simply does a fork() and waits for
its child to die. As you can see from the output, the waitpid
fails. I've tried putting in a sleep() before I exit from
the child but this doesn't help.
This code seems to work fine on ULTRIX and SUNOS, but not on AIX3.2.
Also I've compiled with -D_BSD -lbsd.
It seems like the child dies before the parent calls waitpid(),
but I thought it (the child) just became a zombie until it is collected
by the waitpid.
Does anyone have any clues?
Thanks in advance
---------- PROGRAM ----------
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
main()
{
int pid;
int status;
signal(SIGCHLD, SIG_IGN);
if (pid = fork()) {
printf("Parent: pid=%d childpid=%d \n",getpid(),pid);
if (waitpid(pid, &status, 0) < 0)
perror("waitpid fails");
else
printf("waitpid OK\n");
} else {
printf("Child: pid=%d\n",getpid());
exit(5);
}
}
----------OUTPUT--------------
Child: pid=19726
Parent: pid=15885 childpid=19726
waitpid fails: No child processes
-----------------------------------------------------------------------------------
Khalid Ahmed
Computer Science Research Institute
Univerisity of Toronto
Email: ahm...@white.toronto.edu
-----------------------------------------------------------------------------------
Yes. It looks (though I didn't compile and run the program) that the
problem is not that the child exits to quickly, but that the parent
gets to waitpid() before the child process has even started up, thus
the error message "No child processes".
L. Scott Emmons
CableData Research Center
csusac.csus.edu!cdsac!scotte
KC6NFP
This is the problem. Even though the default action for SIGCHLD is to
SIG_IGN it, setting the action explicitly to SIG_IGN is overloaded to
mean "that the process does not want to receive the SIGCHLD signal when
one of its child process dies, and does not want to have its wait calls
return because a child process is dead (just when no more child proc-
cesses exist, and on stopped child processes)" -- from man 2 signal.
Not bothering to call signal(2) or calling it with a SIG_DFL action
will do what you want.
>
> if (pid = fork()) {
> printf("Parent: pid=%d childpid=%d \n",getpid(),pid);
> if (waitpid(pid, &status, 0) < 0)
> perror("waitpid fails");
> else
> printf("waitpid OK\n");
> } else {
> printf("Child: pid=%d\n",getpid());
> exit(5);
> }
>}
>
--
James R. Hamilton inet: j...@jrh.gts.org
telephone: +1 416 493 4162 uunet: ...!uunet!jrh!jrh
Toronto, Canada bitnet: jrh%j...@uunet.uu.net
>Does anyone have any clues?
>
>Thanks in advance
>
>---------- PROGRAM ----------
>#include <stdio.h>
>#include <signal.h>
>#include <sys/wait.h>
>
>main()
>{
> int pid;
> int status;
>
> signal(SIGCHLD, SIG_IGN);
Here is the culprit. By setting the action for SIGCHLD to ignore, the system
assumes the SysV behaviour and has all your exiting children cleaned up
immediately. Any following wait/waitpid/wait3 call will not return until all the
processes children have exited and then return ENOCHILD. So, although you compiled
for BSD, the overriding behaviour in this case in SysV.
>
> if (pid = fork()) {
> printf("Parent: pid=%d childpid=%d \n",getpid(),pid);
> if (waitpid(pid, &status, 0) < 0)
> perror("waitpid fails");
> else
> printf("waitpid OK\n");
> } else {
> printf("Child: pid=%d\n",getpid());
> exit(5);
> }
>}
>
>----------OUTPUT--------------
>Child: pid=19726
>Parent: pid=15885 childpid=19726
>waitpid fails: No child processes
>
>-----------------------------------------------------------------------------------
>Khalid Ahmed
>Computer Science Research Institute
>Univerisity of Toronto
>Email: ahm...@white.toronto.edu
>-----------------------------------------------------------------------------------
--
Jeff Peek
AIX Operating System Architecture -- IBM Personal Systems Programming
ran...@perelandra.austin.ibm.com VNET PEEK at AUSVM6 T/L 678-3913
Austin, TX