Ejemplo n.º 1
0
static gboolean
child_death_dispatch(int sig, gpointer notused)
{
	int 			status;
	pid_t			pid;
	const int		waitflags = WNOHANG;
	struct sigaction	saveaction;
	int			childcount = 0;

	/*
	 * wait3(WNOHANG) isn't _supposed_ to hang
	 * Unfortunately, it seems to do just that on some OSes.
	 *
	 * The workaround is to set an alarm.  I don't think for this purpose
	 * that it matters if siginterrupt(SIGALRM) is set TRUE or FALSE since
	 * the tiniest little excuse seems to cause the wait3() to finish.
	 */
	
	memset(&saveaction, 0, sizeof(saveaction));
	cl_signal_set_simple_handler(SIGALRM, G_main_alarm_helper, &saveaction);

	alarm_count = 0;
	cl_signal_set_interrupt(SIGALRM, TRUE);
	setmsrepeattimer(WAITALARM); /* Might as well be persistent ;-) */
	while((pid=wait3(&status, waitflags, NULL)) > 0
	||	(pid < 0 && errno == EINTR)) {
		cancelmstimer();
		if (pid > 0) {
			++childcount;
			ReportProcHasDied(pid, status);
		}
		setmsrepeattimer(WAITALARM); /* Let's be persistent ;-) */
	}
	cancelmstimer();
	cl_signal_set_simple_handler(SIGALRM, saveaction.sa_handler, &saveaction);

	if (pid < 0 && errno != ECHILD) {
		cl_perror("%s: wait3() failed"
		,	__FUNCTION__);
	}
#if defined(DEBUG)
	if (childcount < 1) {
		/*
		 * This happens when we receive a SIGCHLD after we clear
		 * 'sig_src->signal_triggered' in G_SIG_dispatch() but
		 * before the last wait3() call returns no child above.
		 */
		cl_log(LOG_DEBUG, "NOTE: %s called without children to wait on"
		,	__FUNCTION__);
	}
#endif
	if (alarm_count) {
		cl_log(LOG_ERR
		,	"%s: wait3() call hung %d times. childcount = %d"
		,	__FUNCTION__, alarm_count, childcount);
		alarm_count = 0;
	}
	return TRUE;
}
Ejemplo n.º 2
0
static void
register_pid(gboolean do_fork,
	     gboolean (*shutdown)(int nsig, gpointer userdata))
{
	int j;
	umask(022);

	for (j = 0; j < 3; ++j) {
		close(j);
		(void)open("/dev/null", j == 0 ? O_RDONLY : O_RDONLY);
	}
	CL_IGNORE_SIG(SIGINT);
	CL_IGNORE_SIG(SIGHUP);
	G_main_add_SignalHandler(G_PRIORITY_HIGH, SIGTERM
	,	 	shutdown, NULL, NULL);
	cl_signal_set_interrupt(SIGTERM, 1);
	cl_signal_set_interrupt(SIGCHLD, 1);
	/* At least they are harmless, I think. ;-) */
	cl_signal_set_interrupt(SIGINT, 0);
	cl_signal_set_interrupt(SIGHUP, 0);
}
Ejemplo n.º 3
0
/*
 *	Add an Signal to the gmainloop world...
 */
GSIGSource*
G_main_add_SignalHandler(int priority, int signal,
			 gboolean (*dispatch)(int nsig, gpointer user_data),
			 gpointer userdata, GDestroyNotify notify)
{
	GSIGSource* sig_src;
	GSource * source = g_source_new(&G_SIG_SourceFuncs, sizeof(GSIGSource));
	gboolean failed = FALSE;
	
	sig_src = (GSIGSource*)source;
	
	sig_src->magno		= MAG_GSIGSOURCE;
	sig_src->maxdispatchdelayms = DEFAULT_MAXDELAY;
	sig_src->maxdispatchms	= DEFAULT_MAXDISPATCH;
	sig_src->signal		= signal;
	sig_src->dispatch	= dispatch;
	sig_src->udata		= userdata;
	sig_src->dnotify	= notify;

	sig_src->signal_triggered = FALSE;

	g_source_set_priority(source, priority);
	g_source_set_can_recurse(source, FALSE);

	if(G_main_signal_list[signal] != NULL) {
		cl_log(LOG_ERR
		,	"%s: Handler already present for signal %d"
		,	__FUNCTION__, signal);
		failed = TRUE;
	}
	if(!failed) {
		sig_src->gsourceid = g_source_attach(source, NULL);
		sig_src->description = "signal";
		if (sig_src->gsourceid < 1) {
			cl_log(LOG_ERR
			,	"%s: Could not attach source for signal %d (%d)"
			,	__FUNCTION__
			,	signal, sig_src->gsourceid);
			failed = TRUE;
		}
	}
	
	if(failed) {
		cl_log(LOG_ERR
		,	"%s: Signal handler for signal %d NOT added"
		,	__FUNCTION__, signal);
		g_source_remove(sig_src->gsourceid);
		g_source_unref(source);
		source = NULL;
		sig_src = NULL;
	} else {
		if (debug_level > 1) {
			cl_log(LOG_DEBUG
			, "%s: Added signal handler for signal %d"
			,	__FUNCTION__, signal);
		}
		G_main_signal_list[signal] = sig_src;
		CL_SIGNAL(signal, G_main_signal_handler);
		/*
		 * If we don't set this on, then the mainloop poll(2) call
		 * will never be interrupted by this signal - which sort of
		 * defeats the whole purpose of a signal handler in a
		 * mainloop program
		 */
		cl_signal_set_interrupt(signal, TRUE);
	}
	return sig_src;
}