Example #1
0
File: mce.c Project: spiiroin/mce
/** 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();
	}
}
Example #2
0
File: mce.c Project: spiiroin/mce
/** 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;
}
Example #3
0
File: mce.c Project: kimmoli/mce
/** 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();
	}
}
Example #4
0
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;
}