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