/** * Signal handler * * @param signr Signal type */ static void signal_handler(const gint signr) { switch (signr) { case SIGUSR1: /* We'll probably want some way to communicate with MCE */ break; case SIGHUP: /* Possibly for re-reading configuration? */ break; case SIGINT: case SIGQUIT: case SIGTERM: /* Just die if we somehow get here without having a mainloop */ if( !mainloop ) { mce_exit_via_signal(signr); } /* Terminate mainloop */ mce_quit_mainloop(); break; case SIGPIPE: break; default: /* Should never happen */ break; } }
/** Signal handler callback for writing signals to pipe * * @param sig the signal number to pass to mainloop via pipe */ static void mce_tx_signal_cb(int sig) { /* NOTE: this function must be kept async-signal-safe! */ static volatile int exit_tries = 0; static const char msg[] = "\n*** BREAK ***\n"; static const char die[] = "\n*** UNRECOVERABLE FAILURE ***\n"; switch( sig ) { case SIGUSR1: case SIGUSR2: case SIGHUP: /* Just pass to mainloop */ break; case SIGINT: case SIGQUIT: case SIGTERM: /* Make sure that a stuck or non-existing mainloop does * not stop us from handling at least repeated terminating signals ... */ #ifdef ENABLE_WAKELOCKS /* We are on exit path -> block suspend for good */ wakelock_block_suspend_until_exit(); #endif no_error_check_write(STDERR_FILENO, msg, sizeof msg - 1); if( !mainloop || ++exit_tries >= 2 ) { mce_abort(); } break; default: /* Assume unrecoverable failure that can't be handled in * the mainloop - disable autosuspend and then terminate * via default signal handler. */ no_error_check_write(STDERR_FILENO, die, sizeof die - 1); mce_exit_via_signal(sig); break; } /* transfer the signal to mainloop via pipe */ int did = TEMP_FAILURE_RETRY(write(signal_pipe[1], &sig, sizeof sig)); if( did != (int)sizeof sig ) { mce_abort(); } }
/** * Signal handler * * @param signr Signal type */ static void signal_handler(const gint signr) { switch (signr) { case SIGUSR1: /* switch to debug verbosity */ mce_log_set_verbosity(LL_DEBUG); mce_log(LL_DEBUG, "switching to DEBUG verbosity level"); break; case SIGUSR2: /* switch to normal verbosity */ mce_log_set_verbosity(LL_DEBUG); mce_log(LL_DEBUG, "switching to WARNING verbosity level"); mce_log_set_verbosity(LL_WARN); break; case SIGHUP: /* Possibly for re-reading configuration? */ break; case SIGINT: case SIGQUIT: case SIGTERM: /* Just die if we somehow get here without having a mainloop */ if( !mainloop ) { mce_exit_via_signal(signr); } /* Terminate mainloop */ mce_quit_mainloop(); break; case SIGPIPE: break; default: /* Should never happen */ break; } }
/** Suspend safe replacement for _exit(1), abort() etc */ void mce_abort(void) { mce_exit_via_signal(SIGABRT); }
/** Signal handler callback for writing signals to pipe * * @param sig the signal number to pass to mainloop via pipe */ static void mce_tx_signal_cb(int sig) { /* NOTE: this function must be kept async-signal-safe! */ static volatile int exit_tries = 0; static const char msg[] = "\n*** BREAK ***\n"; #ifdef ENABLE_WAKELOCKS static const char die[] = "\n*** UNRECOVERABLE FAILURE ***\n"; #endif /* FIXME: Should really use sigaction() to avoid having * the default handler active until we manage to restore * our handler here ... */ signal(sig, mce_tx_signal_cb); switch( sig ) { case SIGINT: case SIGQUIT: case SIGTERM: /* Make sure that a stuck or non-existing mainloop does * not stop us from handling at least repeated terminating signals ... */ #ifdef ENABLE_WAKELOCKS /* We are on exit path -> block suspend for good */ wakelock_block_suspend_until_exit(); #endif no_error_check_write(STDERR_FILENO, msg, sizeof msg - 1); if( !mainloop || ++exit_tries >= 2 ) { mce_abort(); } break; #ifdef ENABLE_WAKELOCKS case SIGABRT: case SIGILL: case SIGFPE: case SIGSEGV: case SIGALRM: case SIGBUS: /* Unrecoverable failures can't be handled in the mainloop * Terminate but disable suspend first */ no_error_check_write(STDERR_FILENO, die, sizeof die - 1); mce_exit_via_signal(sig); break; case SIGTSTP: /* Stopping mce could also lead to unrecoverable suspend */ break; #endif default: break; } /* transfer the signal to mainloop via pipe */ int did = TEMP_FAILURE_RETRY(write(signal_pipe[1], &sig, sizeof sig)); if( did != (int)sizeof sig ) { mce_abort(); } }