#include #include #include #include #include volatile unsigned int have_token = 0; volatile unsigned int signal_count = 0; volatile unsigned int terminate = 0; void sighandler(int signo) { have_token = 1; ++signal_count; } void termination_handler(int signo) { terminate = 1; } void run_member_of_ring(pid_t next) { sigset_t empty_set; sigemptyset(&empty_set); for(;;) { sighold(SIGTERM); sighold(SIGUSR1); if (!have_token && !terminate) { sigsuspend(&empty_set); } sigrelse(SIGTERM); sighold(SIGUSR1); if (terminate) break; if (kill(next, SIGUSR1) < 0) break; have_token = 0; } } pid_t create_tokenring(unsigned int members) { pid_t master = fork(); sighold(SIGTERM); if (master < 0) return master; if (master == 0) { struct sigaction sigact1 = { .sa_handler = sighandler, }; if (sigaction(SIGUSR1, &sigact1, 0) < 0) { exit(255); } master = getpid(); setpgid(master, 0); pid_t next = master; for (unsigned int member = 1; member < members; ++member) { pid_t child = fork(); if (child < 0) { exit(255); } if (child == 0) { sigrelse(SIGTERM); run_member_of_ring(next); exit(0); } setpgid(child, master); next = child; } struct sigaction sigact2 = { .sa_handler = termination_handler, }; if (sigaction(SIGTERM, &sigact2, 0) < 0) { exit(255); } sigrelse(SIGTERM); have_token = 1; run_member_of_ring(next); /* wait for all childs */ int wstat; while (waitpid(-master, &wstat, 0) > 0) { } printf("%u rounds\n", signal_count); exit(0); } sigrelse(SIGTERM); return master; } int main() { pid_t master = create_tokenring(3); sleep(1); kill(-master, SIGTERM); int stat; waitpid(master, &stat, 0); }