signal.c revision 64562
164562Sgshapiro/*
264562Sgshapiro *  Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
464562Sgshapiro *
564562Sgshapiro * By using this file, you agree to the terms and conditions set
664562Sgshapiro * forth in the LICENSE file which can be found at the top level of
764562Sgshapiro * the sendmail distribution.
864562Sgshapiro *
964562Sgshapiro */
1064562Sgshapiro
1164562Sgshapiro#ifndef lint
1264562Sgshapirostatic char id[] = "@(#)$Id: signal.c,v 8.10.4.4 2000/07/14 06:16:57 msk Exp $";
1364562Sgshapiro#endif /* ! lint */
1464562Sgshapiro
1564562Sgshapiro#if _FFR_MILTER
1664562Sgshapiro#include "libmilter.h"
1764562Sgshapiro
1864562Sgshapirotypedef pthread_mutex_t smutex_t;
1964562Sgshapiro#define smutex_init(mp)		(pthread_mutex_init(mp, NULL) == 0)
2064562Sgshapiro#define smutex_destroy(mp)	(pthread_mutex_destroy(mp) == 0)
2164562Sgshapiro#define smutex_lock(mp)		(pthread_mutex_lock(mp) == 0)
2264562Sgshapiro#define smutex_unlock(mp)	(pthread_mutex_unlock(mp) == 0)
2364562Sgshapiro#define smutex_trylock(mp)	(pthread_mutex_trylock(mp) == 0)
2464562Sgshapiro
2564562Sgshapiro/*
2664562Sgshapiro** thread to handle signals
2764562Sgshapiro*/
2864562Sgshapiro
2964562Sgshapirostatic smutex_t M_Mutex;
3064562Sgshapiro
3164562Sgshapirostatic int MilterStop = MILTER_CONT;
3264562Sgshapiro
3364562Sgshapiro/*
3464562Sgshapiro**  MI_STOP -- return value of MilterStop
3564562Sgshapiro**
3664562Sgshapiro**	Parameters:
3764562Sgshapiro**		none.
3864562Sgshapiro**
3964562Sgshapiro**	Returns:
4064562Sgshapiro**		value of MilterStop
4164562Sgshapiro*/
4264562Sgshapiro
4364562Sgshapiroint
4464562Sgshapiromi_stop()
4564562Sgshapiro{
4664562Sgshapiro	return MilterStop;
4764562Sgshapiro}
4864562Sgshapiro/*
4964562Sgshapiro**  MI_STOP_MILTERS -- set value of MilterStop
5064562Sgshapiro**
5164562Sgshapiro**	Parameters:
5264562Sgshapiro**		v -- new value for MilterStop.
5364562Sgshapiro**
5464562Sgshapiro**	Returns:
5564562Sgshapiro**		none.
5664562Sgshapiro*/
5764562Sgshapiro
5864562Sgshapirovoid
5964562Sgshapiromi_stop_milters(v)
6064562Sgshapiro	int v;
6164562Sgshapiro{
6264562Sgshapiro	(void) smutex_lock(&M_Mutex);
6364562Sgshapiro	if (MilterStop < v)
6464562Sgshapiro		MilterStop = v;
6564562Sgshapiro	(void) smutex_unlock(&M_Mutex);
6664562Sgshapiro}
6764562Sgshapiro/*
6864562Sgshapiro**  MI_CLEAN_SIGNALS -- clean up signal handler thread
6964562Sgshapiro**
7064562Sgshapiro**	Parameters:
7164562Sgshapiro**		none.
7264562Sgshapiro**
7364562Sgshapiro**	Returns:
7464562Sgshapiro**		none.
7564562Sgshapiro*/
7664562Sgshapiro
7764562Sgshapirovoid
7864562Sgshapiromi_clean_signals()
7964562Sgshapiro{
8064562Sgshapiro	(void) smutex_destroy(&M_Mutex);
8164562Sgshapiro}
8264562Sgshapiro/*
8364562Sgshapiro**  MI_SIGNAL_THREAD -- thread to deal with signals
8464562Sgshapiro**
8564562Sgshapiro**	Parameters:
8664562Sgshapiro**		name -- name of milter
8764562Sgshapiro**
8864562Sgshapiro**	Returns:
8964562Sgshapiro**		NULL
9064562Sgshapiro*/
9164562Sgshapiro
9264562Sgshapirostatic void *
9364562Sgshapiromi_signal_thread(name)
9464562Sgshapiro	void *name;
9564562Sgshapiro{
9664562Sgshapiro	int sig, errs;
9764562Sgshapiro	sigset_t set;
9864562Sgshapiro
9964562Sgshapiro	sigemptyset(&set);
10064562Sgshapiro	sigaddset(&set, SIGHUP);
10164562Sgshapiro	sigaddset(&set, SIGTERM);
10264562Sgshapiro
10364562Sgshapiro	/* Handle Ctrl-C gracefully for debugging */
10464562Sgshapiro	sigaddset(&set, SIGINT);
10564562Sgshapiro	errs = 0;
10664562Sgshapiro
10764562Sgshapiro	while (TRUE)
10864562Sgshapiro	{
10964562Sgshapiro		sig = 0;
11064562Sgshapiro#ifdef SOLARIS
11164562Sgshapiro		if ((sig = sigwait(&set)) < 0)
11264562Sgshapiro#else /* SOLARIS */
11364562Sgshapiro		if (sigwait(&set, &sig) != 0)
11464562Sgshapiro#endif /* SOLARIS */
11564562Sgshapiro		{
11664562Sgshapiro			smi_log(SMI_LOG_ERR,
11764562Sgshapiro				"%s: sigwait returned error: %s",
11864562Sgshapiro				(char *)name, strerror(errno));
11964562Sgshapiro			if (++errs > MAX_FAILS_T)
12064562Sgshapiro			{
12164562Sgshapiro				mi_stop_milters(MILTER_ABRT);
12264562Sgshapiro				return NULL;
12364562Sgshapiro			}
12464562Sgshapiro			continue;
12564562Sgshapiro		}
12664562Sgshapiro		errs = 0;
12764562Sgshapiro
12864562Sgshapiro		switch (sig)
12964562Sgshapiro		{
13064562Sgshapiro		  case SIGHUP:
13164562Sgshapiro		  case SIGTERM:
13264562Sgshapiro			mi_stop_milters(MILTER_STOP);
13364562Sgshapiro			return NULL;
13464562Sgshapiro		  case SIGINT:
13564562Sgshapiro			mi_stop_milters(MILTER_ABRT);
13664562Sgshapiro			return NULL;
13764562Sgshapiro		  default:
13864562Sgshapiro			smi_log(SMI_LOG_ERR,
13964562Sgshapiro				"%s: sigwait returned unmasked signal: %d",
14064562Sgshapiro				(char *)name, sig);
14164562Sgshapiro			break;
14264562Sgshapiro		}
14364562Sgshapiro	}
14464562Sgshapiro}
14564562Sgshapiro/*
14664562Sgshapiro**  MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals
14764562Sgshapiro**
14864562Sgshapiro**	Parameters:
14964562Sgshapiro**		name -- name of milter
15064562Sgshapiro**
15164562Sgshapiro**	Returns:
15264562Sgshapiro**		MI_SUCCESS/MI_FAILURE
15364562Sgshapiro*/
15464562Sgshapiro
15564562Sgshapirostatic int
15664562Sgshapiromi_spawn_signal_thread(name)
15764562Sgshapiro	char *name;
15864562Sgshapiro{
15964562Sgshapiro	sthread_t tid;
16064562Sgshapiro	sigset_t set;
16164562Sgshapiro
16264562Sgshapiro	/* Mask HUP and KILL signals */
16364562Sgshapiro	sigemptyset(&set);
16464562Sgshapiro	sigaddset(&set, SIGHUP);
16564562Sgshapiro	sigaddset(&set, SIGTERM);
16664562Sgshapiro	sigaddset(&set, SIGINT);
16764562Sgshapiro
16864562Sgshapiro	if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
16964562Sgshapiro	{
17064562Sgshapiro		smi_log(SMI_LOG_ERR,
17164562Sgshapiro			"%s: Couldn't mask HUP and KILL signals", name);
17264562Sgshapiro		return MI_FAILURE;
17364562Sgshapiro	}
17464562Sgshapiro	if (thread_create(&tid, mi_signal_thread,
17564562Sgshapiro			  (void *)name) != MI_SUCCESS)
17664562Sgshapiro	{
17764562Sgshapiro		smi_log(SMI_LOG_ERR,
17864562Sgshapiro			"%s: Couldn't start signal thread", name);
17964562Sgshapiro		return MI_FAILURE;
18064562Sgshapiro	}
18164562Sgshapiro	return MI_SUCCESS;
18264562Sgshapiro}
18364562Sgshapiro/*
18464562Sgshapiro**  MI_CONTROL_STARTUP -- startup for thread to handle signals
18564562Sgshapiro**
18664562Sgshapiro**	Parameters:
18764562Sgshapiro**		name -- name of milter
18864562Sgshapiro**
18964562Sgshapiro**	Returns:
19064562Sgshapiro**		MI_SUCCESS/MI_FAILURE
19164562Sgshapiro*/
19264562Sgshapiro
19364562Sgshapiroint
19464562Sgshapiromi_control_startup(name)
19564562Sgshapiro	char *name;
19664562Sgshapiro{
19764562Sgshapiro
19864562Sgshapiro	if (!smutex_init(&M_Mutex))
19964562Sgshapiro	{
20064562Sgshapiro		smi_log(SMI_LOG_ERR,
20164562Sgshapiro			"%s: Couldn't initialize control pipe mutex", name);
20264562Sgshapiro		return MI_FAILURE;
20364562Sgshapiro	}
20464562Sgshapiro
20564562Sgshapiro	/*
20664562Sgshapiro	**  spawn_signal_thread must happen before other threads are spawned
20764562Sgshapiro	**  off so that it can mask the right signals and other threads
20864562Sgshapiro	**  will inherit that mask.
20964562Sgshapiro	*/
21064562Sgshapiro	if (mi_spawn_signal_thread(name) == MI_FAILURE)
21164562Sgshapiro	{
21264562Sgshapiro		smi_log(SMI_LOG_ERR,
21364562Sgshapiro			"%s: Couldn't spawn signal thread", name);
21464562Sgshapiro		(void) smutex_destroy(&M_Mutex);
21564562Sgshapiro		return MI_FAILURE;
21664562Sgshapiro	}
21764562Sgshapiro	return MI_SUCCESS;
21864562Sgshapiro}
21964562Sgshapiro#endif /* _FFR_MILTER */
220