signal.c revision 66494
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
1266494Sgshapirostatic char id[] = "@(#)$Id: signal.c,v 8.10.4.7 2000/09/01 00:49:04 ca Exp $";
1364562Sgshapiro#endif /* ! lint */
1464562Sgshapiro
1564562Sgshapiro#if _FFR_MILTER
1664562Sgshapiro#include "libmilter.h"
1764562Sgshapiro
1864562Sgshapirotypedef pthread_mutex_t smutex_t;
1966494Sgshapiro# define smutex_init(mp)	(pthread_mutex_init(mp, NULL) == 0)
2066494Sgshapiro# define smutex_destroy(mp)	(pthread_mutex_destroy(mp) == 0)
2166494Sgshapiro# define smutex_lock(mp)	(pthread_mutex_lock(mp) == 0)
2266494Sgshapiro# define smutex_unlock(mp)	(pthread_mutex_unlock(mp) == 0)
2366494Sgshapiro# define smutex_trylock(mp)	(pthread_mutex_trylock(mp) == 0)
2464562Sgshapiro
2564562Sgshapiro/*
2666494Sgshapiro**  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;
6566494Sgshapiro
6666494Sgshapiro	/* close listen socket */
6766494Sgshapiro	mi_closener();
6864562Sgshapiro	(void) smutex_unlock(&M_Mutex);
6964562Sgshapiro}
7064562Sgshapiro/*
7164562Sgshapiro**  MI_CLEAN_SIGNALS -- clean up signal handler thread
7264562Sgshapiro**
7364562Sgshapiro**	Parameters:
7464562Sgshapiro**		none.
7564562Sgshapiro**
7664562Sgshapiro**	Returns:
7764562Sgshapiro**		none.
7864562Sgshapiro*/
7964562Sgshapiro
8064562Sgshapirovoid
8164562Sgshapiromi_clean_signals()
8264562Sgshapiro{
8364562Sgshapiro	(void) smutex_destroy(&M_Mutex);
8464562Sgshapiro}
8564562Sgshapiro/*
8664562Sgshapiro**  MI_SIGNAL_THREAD -- thread to deal with signals
8764562Sgshapiro**
8864562Sgshapiro**	Parameters:
8964562Sgshapiro**		name -- name of milter
9064562Sgshapiro**
9164562Sgshapiro**	Returns:
9264562Sgshapiro**		NULL
9364562Sgshapiro*/
9464562Sgshapiro
9564562Sgshapirostatic void *
9664562Sgshapiromi_signal_thread(name)
9764562Sgshapiro	void *name;
9864562Sgshapiro{
9964562Sgshapiro	int sig, errs;
10064562Sgshapiro	sigset_t set;
10164562Sgshapiro
10264562Sgshapiro	sigemptyset(&set);
10364562Sgshapiro	sigaddset(&set, SIGHUP);
10464562Sgshapiro	sigaddset(&set, SIGTERM);
10564562Sgshapiro
10664562Sgshapiro	/* Handle Ctrl-C gracefully for debugging */
10764562Sgshapiro	sigaddset(&set, SIGINT);
10864562Sgshapiro	errs = 0;
10964562Sgshapiro
11064562Sgshapiro	while (TRUE)
11164562Sgshapiro	{
11264562Sgshapiro		sig = 0;
11364562Sgshapiro#ifdef SOLARIS
11464562Sgshapiro		if ((sig = sigwait(&set)) < 0)
11564562Sgshapiro#else /* SOLARIS */
11664562Sgshapiro		if (sigwait(&set, &sig) != 0)
11764562Sgshapiro#endif /* SOLARIS */
11864562Sgshapiro		{
11964562Sgshapiro			smi_log(SMI_LOG_ERR,
12064562Sgshapiro				"%s: sigwait returned error: %s",
12164562Sgshapiro				(char *)name, strerror(errno));
12264562Sgshapiro			if (++errs > MAX_FAILS_T)
12364562Sgshapiro			{
12464562Sgshapiro				mi_stop_milters(MILTER_ABRT);
12564562Sgshapiro				return NULL;
12664562Sgshapiro			}
12764562Sgshapiro			continue;
12864562Sgshapiro		}
12964562Sgshapiro		errs = 0;
13064562Sgshapiro
13164562Sgshapiro		switch (sig)
13264562Sgshapiro		{
13364562Sgshapiro		  case SIGHUP:
13464562Sgshapiro		  case SIGTERM:
13564562Sgshapiro			mi_stop_milters(MILTER_STOP);
13664562Sgshapiro			return NULL;
13764562Sgshapiro		  case SIGINT:
13864562Sgshapiro			mi_stop_milters(MILTER_ABRT);
13964562Sgshapiro			return NULL;
14064562Sgshapiro		  default:
14164562Sgshapiro			smi_log(SMI_LOG_ERR,
14264562Sgshapiro				"%s: sigwait returned unmasked signal: %d",
14364562Sgshapiro				(char *)name, sig);
14464562Sgshapiro			break;
14564562Sgshapiro		}
14664562Sgshapiro	}
14764562Sgshapiro}
14864562Sgshapiro/*
14964562Sgshapiro**  MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals
15064562Sgshapiro**
15164562Sgshapiro**	Parameters:
15264562Sgshapiro**		name -- name of milter
15364562Sgshapiro**
15464562Sgshapiro**	Returns:
15564562Sgshapiro**		MI_SUCCESS/MI_FAILURE
15664562Sgshapiro*/
15764562Sgshapiro
15864562Sgshapirostatic int
15964562Sgshapiromi_spawn_signal_thread(name)
16064562Sgshapiro	char *name;
16164562Sgshapiro{
16264562Sgshapiro	sthread_t tid;
16364562Sgshapiro	sigset_t set;
16464562Sgshapiro
16564562Sgshapiro	/* Mask HUP and KILL signals */
16664562Sgshapiro	sigemptyset(&set);
16764562Sgshapiro	sigaddset(&set, SIGHUP);
16864562Sgshapiro	sigaddset(&set, SIGTERM);
16964562Sgshapiro	sigaddset(&set, SIGINT);
17064562Sgshapiro
17164562Sgshapiro	if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
17264562Sgshapiro	{
17364562Sgshapiro		smi_log(SMI_LOG_ERR,
17464562Sgshapiro			"%s: Couldn't mask HUP and KILL signals", name);
17564562Sgshapiro		return MI_FAILURE;
17664562Sgshapiro	}
17764562Sgshapiro	if (thread_create(&tid, mi_signal_thread,
17864562Sgshapiro			  (void *)name) != MI_SUCCESS)
17964562Sgshapiro	{
18064562Sgshapiro		smi_log(SMI_LOG_ERR,
18164562Sgshapiro			"%s: Couldn't start signal thread", name);
18264562Sgshapiro		return MI_FAILURE;
18364562Sgshapiro	}
18464562Sgshapiro	return MI_SUCCESS;
18564562Sgshapiro}
18664562Sgshapiro/*
18764562Sgshapiro**  MI_CONTROL_STARTUP -- startup for thread to handle signals
18864562Sgshapiro**
18964562Sgshapiro**	Parameters:
19064562Sgshapiro**		name -- name of milter
19164562Sgshapiro**
19264562Sgshapiro**	Returns:
19364562Sgshapiro**		MI_SUCCESS/MI_FAILURE
19464562Sgshapiro*/
19564562Sgshapiro
19664562Sgshapiroint
19764562Sgshapiromi_control_startup(name)
19864562Sgshapiro	char *name;
19964562Sgshapiro{
20064562Sgshapiro
20164562Sgshapiro	if (!smutex_init(&M_Mutex))
20264562Sgshapiro	{
20364562Sgshapiro		smi_log(SMI_LOG_ERR,
20464562Sgshapiro			"%s: Couldn't initialize control pipe mutex", name);
20564562Sgshapiro		return MI_FAILURE;
20664562Sgshapiro	}
20764562Sgshapiro
20864562Sgshapiro	/*
20964562Sgshapiro	**  spawn_signal_thread must happen before other threads are spawned
21064562Sgshapiro	**  off so that it can mask the right signals and other threads
21164562Sgshapiro	**  will inherit that mask.
21264562Sgshapiro	*/
21364562Sgshapiro	if (mi_spawn_signal_thread(name) == MI_FAILURE)
21464562Sgshapiro	{
21564562Sgshapiro		smi_log(SMI_LOG_ERR,
21664562Sgshapiro			"%s: Couldn't spawn signal thread", name);
21764562Sgshapiro		(void) smutex_destroy(&M_Mutex);
21864562Sgshapiro		return MI_FAILURE;
21964562Sgshapiro	}
22064562Sgshapiro	return MI_SUCCESS;
22164562Sgshapiro}
22264562Sgshapiro#endif /* _FFR_MILTER */
223