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