/*
* sig_purgechilds.c
*
* The parent process pulls a child exit status whenever the OS notifies
* a child status change.
*
* Created by Mij <mij@bitchx.it> on 04/01/05.
* Original source file available at http://mij.oltrelinux.com/devel/unixprg/
*
*/
/* for printf() and fgetc() */
#include <stdio.h>
/* for fork() */
#include <sys/types.h>
#include <unistd.h>
/* for srandom() and random() */
#include <stdlib.h>
/* for time() [seeding srandom()] */
#include <time.h>
/* for waitpid() */
#include <sys/wait.h>
/* for signal(), kill() and raise() */
#include <signal.h>
/* how many childs to raise */
#define NUM_PROCS 5
/* handler prototype for SIGCHLD */
void child_handler(int);
int main(int argc, char *argv[])
{
int i, exit_status;
/* execute child_handler() when receiving a signal of type SIGCHLD */
signal(SIGCHLD, &child_handler);
/* initialize the random num generator */
srandom(time(NULL));
printf("Try to issue a \'ps\' while the process is running...\n");
/* produce NUM_PROCS childs */
for (i = 0; i < NUM_PROCS; i++) {
if (! fork()) {
/* child */
/* choosing a random exit status between 0 and 99 */
exit_status = (int)(random() % 100);
printf(" -> New child %d, will exit with %d.\n", (int)getpid(), exit_status);
/* try to skip signals overlapping */
sleep((unsigned int)(random() % 3));
/* choosing a value to exit between 0 and 99 */
exit(exit_status);
}
/* father */
sleep((unsigned int)(random() % 2));
}
/* checkpoint */
printf("parent: done with fork()ing.\n");
/* why this is not equivalent to sleep(20) here? */
for (i = 0; i < 10; i++) {
sleep(1);
}
/* all the child processes should be done now */
printf("I did not purge all the childs. Timeout; exiting.\n");
/* terminate myself => exit */
kill(getpid(), 15);
/* this won't be actually executed */
return 0;
}
/* handler definition for SIGCHLD */
void child_handler(int sig_type)
{
int child_status;
pid_t child;
static int call_num = 0;
/* getting the child's exit status */
child = waitpid(0, &child_status, 0);
printf("<- Child %d exited with status %d.\n", child, WEXITSTATUS(child_status));
/* did we get all the childs? */
if (++call_num >= NUM_PROCS) {
printf("I got all the childs this time. Going to exit.\n");
exit (0);
}
return;
}