#include /* for errno() */ #include /* for ARG_MAX */ #include /* for signal(), SIG* */ #include /* for sprintf(), stderr, ... */ #include /* for exit() */ #include /* for strerror() */ #include /* for wait() */ #include /* for wait() */ #include /* for sleep(), fork() and execlp() */ #include "funcs.h" /* for infomsg(), errormsg() */ /* * Macros */ #define CHILD_RUN_TIME 10 /* * Type and struct definitions */ /* * Global variables */ int child_reaped = FALSE; /* * Forward declarations */ pid_t start_child_sleep(void); void sigchld_handler(int); /* * Functions */ int main( int argc, char *argv[]) { pid_t pid; /* * Initialise. */ infomsg("parent setting up signal handlers ..."); signal(SIGCHLD, sigchld_handler); /* * Start child. */ infomsg("parent starting one child ..."); pid = start_child_sleep(); /* * Main monitoring loop */ infomsg("parent sees child has pid %d and loops checking flag ...", pid); while (TRUE) { /* * Exit if no running children. */ if (child_reaped) { infomsg("parent sees child_reaped flag and so stops looping ..."); break; } /* * Let a little time pass before we reinspect the situation. */ sleep(1); } /* * Clean up and exit. */ infomsg("parent cleaning up and exiting ..."); signal(SIGCHLD, SIG_DFL); return(0); } pid_t start_child_sleep( ) { pid_t pid; char buf[ARG_MAX]; if ((pid=fork()) < 0) errormsg("fork() failed: %s", strerror(errno)); else if (pid > 0) return(pid); /* * Only the child gets here */ sprintf(buf, "echo \"child running ...\";" "sleep %d;" "echo \"child exiting ...\"", CHILD_RUN_TIME); execlp("/bin/sh", "sh", "-c", buf, (char *) NULL); errormsg("exec() failed: %s", strerror(errno)); } void sigchld_handler( int sig) { int wstatus; pid_t pid; infomsg("parent received SIGCHLD; reaping and setting child_reaped flag ..."); pid = wait(&wstatus); child_reaped = TRUE; }