/** 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(); } }
/** GIO callback for reading signals from pipe * * @param channel io channel for signal pipe * @param condition call reason * @param data user data * * @return TRUE (or aborts on error) */ static gboolean mce_rx_signal_cb(GIOChannel *channel, GIOCondition condition, gpointer data) { // we just want the cb ... (void)channel; (void)condition; (void)data; int sig = 0; int got = TEMP_FAILURE_RETRY(read(signal_pipe[0], &sig, sizeof sig)); if( got != sizeof sig ) { mce_abort(); } /* handle the signal */ signal_handler(sig); /* keep the io watch */ return TRUE; }
/** 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(); } }
gboolean mce_write_number_string_to_file(output_state_t *output, const gulong number) { gboolean status = FALSE; // assume failure if( !output ) { mce_log(LL_CRIT, "NULL output passed, terminating"); mce_abort(); } if( !output->context ) { mce_log(LL_CRIT, "output->context missing, terminating"); mce_abort(); } if( !output->path ) { if( !output->invalid_config_reported ) { output->invalid_config_reported = TRUE; mce_log(LL_ERR, "%s: output->path not configured", output->context); } goto EXIT; } if( !output->file ) { output->file = fopen(output->path, output->truncate_file ? "w" : "a"); if( !output->file ) { mce_log(LL_ERR,"%s: can't open %s: %m", output->context, output->path); goto EXIT; } } else if( output->truncate_file ) { rewind(output->file); if( ftruncate(fileno(output->file), 0) == -1 ) { mce_log(LL_WARN,"%s: can't truncate %s: %m", output->context, output->path); } } // from now on assume success status = TRUE; if( fprintf(output->file, "%lu", number) < 0 ) { mce_log(LL_WARN,"%s: can't write %s: %m", output->context, output->path); status = FALSE; } if( fflush(output->file) == EOF ) { mce_log(LL_WARN,"%s: can't flush %s: %m", output->context, output->path); status = FALSE; } EXIT: if( output->close_on_exit && output->file ) { if( fclose(output->file) == EOF ) { mce_log(LL_WARN,"%s: can't close %s: %m", output->context, output->path); } output->file = 0; } return status; }