void _bridge_signal_handler_for(int signal_number, signal_handler_t old_handler) { // There are five cases interesting here: // 1) The user has no handler set. Then we decide to exit (and destroy the // bridge) by calling exit(). // 2) The user has a handler set and ignores the signal. Then we ignore it too // and everything can go on normally. // 3) The user has a handler set and calls exit() at the end. Then our bridge // will be destroyed via the function we registered with atexit() (all good). // 4) The signal is SIGABRT (abort) and the user has a handler set and exits // the program via exit(). Then our handler will be called and we're good. // 5) The signal is SIGABRT (abort) and the user has a handler set and returns // from his handler. According to the man pages, when a signal handler for // SIGABRT returns, it replaces the current handler with the default handler // (which does a core dump) and re-raises the SIGABRT signal. So when we // call the user's handler for SIGABRT and he returns, we kill the bridge // because we know (and hopefully the user knew) that the process will be // terminated anyway. // Note: PostGres seems to ignore SIGINT at one point. SQLite exit()s after // three SIGINTs are sent (maybe to prevent accidental ^C from killing it...) if (old_handler != NULL) { old_handler(signal_number); } else { exit(EXIT_FAILURE); } if (signal_number == SIGABRT) { bridge_destroy(&bridge); } }
static int bridge_if_destroy(struct bridge_if *bif) { if (bridge_destroy(bif->bif_name) < 0) return (-1); bridge_remove_bif(bif); return (0); }
void _bridge_exit_handler() { bridge_destroy(&bridge); }