static void init_fatal_signal_set (void) { static bool fatal_signal_set_initialized = false; if (!fatal_signal_set_initialized) { size_t i; init_fatal_signals (); sigemptyset (&fatal_signal_set); for (i = 0; i < num_fatal_signals; i++) if (fatal_signals[i] >= 0) sigaddset (&fatal_signal_set, fatal_signals[i]); fatal_signal_set_initialized = true; } }
/* Register a cleanup function to be executed when a catchable fatal signal occurs. */ void at_fatal_signal (action_t action) { static bool cleanup_initialized = false; if (!cleanup_initialized) { init_fatal_signals (); install_handlers (); cleanup_initialized = true; } if (actions_count == actions_allocated) { /* Extend the actions array. Note that we cannot use xrealloc(), because then the cleanup() function could access an already deallocated array. */ actions_entry_t *old_actions = actions; size_t old_actions_allocated = actions_allocated; size_t new_actions_allocated = 2 * actions_allocated; actions_entry_t *new_actions = XNMALLOC (new_actions_allocated, actions_entry_t); size_t k; /* Don't use memcpy() here, because memcpy takes non-volatile arguments and is therefore not guaranteed to complete all memory stores before the next statement. */ for (k = 0; k < old_actions_allocated; k++) new_actions[k] = old_actions[k]; actions = new_actions; actions_allocated = new_actions_allocated; /* Now we can free the old actions array. */ if (old_actions != static_actions) free (old_actions); } /* The two uses of 'volatile' in the types above (and ISO C 99 section 5.1.2.3.(5)) ensure that we increment the actions_count only after the new action has been written to the memory location actions[actions_count]. */ actions[actions_count].action = action; actions_count++; }
static void parachute_init_signals(int child) { struct sigaction sa; if (child_actions_init && child) { sigaction(SIGTERM, &child_actions[SIGTERM], NULL); sigaction(SIGQUIT, &child_actions[SIGQUIT], NULL); sigaction(SIGINT, &child_actions[SIGINT], NULL); sigaction(SIGABRT, &child_actions[SIGABRT], NULL); sigaction(SIGHUP, &child_actions[SIGHUP], NULL); sigaction(SIGALRM, &child_actions[SIGALRM], NULL); sigaction(SIGUSR1, &child_actions[SIGUSR1], NULL); sigaction(SIGUSR2, &child_actions[SIGUSR2], NULL); sigaction(SIGPIPE, &child_actions[SIGPIPE], NULL); } else if (!child && !child_actions_init) { sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = parachute_sig_handler; sigaction(SIGTERM, &sa, &child_actions[SIGTERM]); sigaction(SIGQUIT, &sa, &child_actions[SIGQUIT]); sigaction(SIGINT, &sa, &child_actions[SIGINT]); sigaction(SIGABRT, &sa, &child_actions[SIGABRT]); sigaction(SIGHUP, &sa, &child_actions[SIGHUP]); sigaction(SIGALRM, &sa, &child_actions[SIGALRM]); sigaction(SIGUSR1, &sa, &child_actions[SIGUSR1]); sigaction(SIGUSR2, &sa, &child_actions[SIGUSR2]); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &child_actions[SIGPIPE]); sigaction(SIGTTOU, &sa, NULL); sigaction(SIGTTIN, &sa, NULL); sigaction(SIGTSTP, &sa, NULL); child_actions_init = 1; init_fatal_signals(); } else panic(0, "Child process signal handlers not initialized before."); }