#include #include #include #include #include #include #define TRUE 1 #define FALSE 0 typedef void (*sigfunc_t)(); int QueueIntvl = 4; volatile int DoQueueRun; volatile int tick_cnt = 0; volatile int child_cnt = 0; sigfunc_t setsignal(sig, handler) int sig; sigfunc_t handler; { return signal(sig, handler); } int blocksignal(sig) int sig; { sigset_t sset, oset; sigemptyset(&sset); sigaddset(&sset, sig); if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0) { perror ("sigprocmask"); exit (1); } else return sigismember(&oset, sig); } int releasesignal(sig) int sig; { sigset_t sset, oset; sigemptyset(&sset); sigaddset(&sset, sig); if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0) { perror ("sigprocmask"); exit (1); } else return sigismember(&oset, sig); } void tick(int sig) { tick_cnt++; DoQueueRun = TRUE; } void setevent(intvl) time_t intvl; { int wasblocked; wasblocked = blocksignal(SIGALRM); setsignal(SIGALRM, tick); (void) alarm((unsigned) intvl); if (wasblocked == 0) (void) releasesignal(SIGALRM); printf ("Requested tick\n"); } void reapchild(int sig) { pid_t pid; int status; child_cnt++; pid = waitpid(-1, &status, WNOHANG); if (pid <= 0) { printf("waitpid failed!\n"); exit (1); } } int runqueue(void) { pid_t pid; printf ("Setting DoQueueRun FALSE\n"); DoQueueRun = FALSE; blocksignal(SIGCHLD); (void) setsignal(SIGCHLD, reapchild); pid = fork(); if (pid == -1) { perror ("fork"); exit (1); } if (pid != 0) { /* parent -- pick up intermediate zombie */ printf("Child %d\n", pid); releasesignal(SIGCHLD); setevent(QueueIntvl); return TRUE; } /* Child exits */ exit (0); } int main (int argc, char **argv) { int cnt = 0; int last_tick_cnt, last_child_cnt, new_tick_cnt, new_child_cnt; runqueue(); for (;;) { printf ("Pause %d\n", cnt++); last_tick_cnt = tick_cnt; last_child_cnt = child_cnt; pause(); new_tick_cnt = tick_cnt; new_child_cnt = child_cnt; if (last_tick_cnt == new_tick_cnt && last_child_cnt == new_child_cnt) { int loop = 0; printf ("Hmm, seems we came off pause for no reason.\n"); printf ("Looping waiting for sig hander to finish\n"); while (last_tick_cnt == tick_cnt && last_child_cnt == child_cnt) loop++; printf ("Handler ran, loop %d (tick %d -> %d, child %d -> %d)\n", loop, last_tick_cnt, tick_cnt, last_child_cnt, child_cnt); } if (DoQueueRun) (void) runqueue(); else printf ("DoQueueRun FALSE (tick %d -> %d, child %d -> %d)\n", last_tick_cnt, tick_cnt, last_child_cnt, child_cnt); } return 0; }