DF-5773 / storm_demo.c
/* * DF-5773 mechanism harness -- a faithful, self-contained extraction of * sys/platform/vkernel64/platform/init.c's monitor/child structure: * * init.c:204 while ((childpid = fork()) != 0) { * init.c:206-211 SIG_IGN for INT/QUIT/HUP * init.c:217-218 sa.sa_handler = handle_term; sigaction(SIGTERM,...) * init.c:224-227 waitpid() ... * init.c:228 if (WEXITSTATUS(status) != EX_VKERNEL_REBOOT) return 0; * init.c:500-506 handle_term: kill(childpid, sig) * * First-generation children inherit SIG_DFL for SIGTERM (the sigaction * calls execute in the monitor AFTER fork). After the child exits 32 * (cpu_reset), the monitor reforks -- and THIS child inherits * handle_term with childpid == 0, so a SIGTERM delivered during its * "boot window" executes kill(0, SIGTERM): the whole process group, * including itself (re-armed on handler exit: a self-sustaining storm) * and every bystander in the pgrp. * * usage: storm_demo <window_seconds> * Observe from a runner with a sleeper sibling in the same pgrp. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <time.h> #include <sys/wait.h> #define EX_VKERNEL_REBOOT 32 static pid_t childpid; static void handle_term(int sig) { kill(childpid, sig); } /* init.c:505 */ static void pause_ms(int sec); int main(int ac, char **av) { struct sigaction sa; int window = ac > 1 ? atoi(av[1]) : 5; int status; while ((childpid = fork()) != 0) { memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_IGN; sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sa.sa_handler = handle_term; sigaction(SIGTERM, &sa, NULL); while (waitpid(childpid, &status, 0) != childpid) { /* ECHILD only; keep waiting otherwise (init.c:224-227) */ } if (WEXITSTATUS(status) != EX_VKERNEL_REBOOT) return 0; /* refork: the reboot cycle (init.c:228-230) */ } /* child: "boot" -- the pre-initshutdown window */ pause_ms(window); _exit(EX_VKERNEL_REBOOT); /* cpu_reset() */ return 0; } static void pause_ms(int sec) { struct timespec ts = { sec, 0 }; nanosleep(&ts, NULL); } |