164562Sgshapiro/* 2261194Sgshapiro * Copyright (c) 1999-2004, 2006 Proofpoint, 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 1190792Sgshapiro#include <sm/gen.h> 12266527SgshapiroSM_RCSID("@(#)$Id: signal.c,v 8.45 2013-11-22 20:51:36 ca Exp $") 1364562Sgshapiro 1464562Sgshapiro#include "libmilter.h" 1564562Sgshapiro 1664562Sgshapiro/* 1766494Sgshapiro** thread to handle signals 1864562Sgshapiro*/ 1964562Sgshapiro 2064562Sgshapirostatic smutex_t M_Mutex; 2164562Sgshapiro 2264562Sgshapirostatic int MilterStop = MILTER_CONT; 2364562Sgshapiro 24141858Sgshapirostatic void *mi_signal_thread __P((void *)); 25141858Sgshapirostatic int mi_spawn_signal_thread __P((char *)); 26141858Sgshapiro 2790792Sgshapiro/* 2864562Sgshapiro** MI_STOP -- return value of MilterStop 2964562Sgshapiro** 3064562Sgshapiro** Parameters: 3164562Sgshapiro** none. 3264562Sgshapiro** 3364562Sgshapiro** Returns: 3464562Sgshapiro** value of MilterStop 3564562Sgshapiro*/ 3664562Sgshapiro 3764562Sgshapiroint 3864562Sgshapiromi_stop() 3964562Sgshapiro{ 4064562Sgshapiro return MilterStop; 4164562Sgshapiro} 4290792Sgshapiro/* 4364562Sgshapiro** MI_STOP_MILTERS -- set value of MilterStop 4464562Sgshapiro** 4564562Sgshapiro** Parameters: 4664562Sgshapiro** v -- new value for MilterStop. 4764562Sgshapiro** 4864562Sgshapiro** Returns: 4964562Sgshapiro** none. 5064562Sgshapiro*/ 5164562Sgshapiro 5264562Sgshapirovoid 5364562Sgshapiromi_stop_milters(v) 5464562Sgshapiro int v; 5564562Sgshapiro{ 5664562Sgshapiro (void) smutex_lock(&M_Mutex); 5764562Sgshapiro if (MilterStop < v) 5864562Sgshapiro MilterStop = v; 5966494Sgshapiro 6066494Sgshapiro /* close listen socket */ 6166494Sgshapiro mi_closener(); 6264562Sgshapiro (void) smutex_unlock(&M_Mutex); 6364562Sgshapiro} 6490792Sgshapiro/* 6564562Sgshapiro** MI_CLEAN_SIGNALS -- clean up signal handler thread 6664562Sgshapiro** 6764562Sgshapiro** Parameters: 6864562Sgshapiro** none. 6964562Sgshapiro** 7064562Sgshapiro** Returns: 7164562Sgshapiro** none. 7264562Sgshapiro*/ 7364562Sgshapiro 7464562Sgshapirovoid 7564562Sgshapiromi_clean_signals() 7664562Sgshapiro{ 7764562Sgshapiro (void) smutex_destroy(&M_Mutex); 7864562Sgshapiro} 7990792Sgshapiro/* 8064562Sgshapiro** MI_SIGNAL_THREAD -- thread to deal with signals 8164562Sgshapiro** 8264562Sgshapiro** Parameters: 8364562Sgshapiro** name -- name of milter 8464562Sgshapiro** 8564562Sgshapiro** Returns: 8664562Sgshapiro** NULL 8764562Sgshapiro*/ 8864562Sgshapiro 8964562Sgshapirostatic void * 9064562Sgshapiromi_signal_thread(name) 9164562Sgshapiro void *name; 9264562Sgshapiro{ 93157001Sgshapiro int sig, errs, sigerr; 9464562Sgshapiro sigset_t set; 9564562Sgshapiro 96120256Sgshapiro (void) sigemptyset(&set); 97120256Sgshapiro (void) sigaddset(&set, SIGHUP); 98120256Sgshapiro (void) sigaddset(&set, SIGTERM); 9964562Sgshapiro 10064562Sgshapiro /* Handle Ctrl-C gracefully for debugging */ 101120256Sgshapiro (void) sigaddset(&set, SIGINT); 10264562Sgshapiro errs = 0; 10364562Sgshapiro 104120256Sgshapiro for (;;) 10564562Sgshapiro { 106157001Sgshapiro sigerr = sig = 0; 107285229Sgshapiro#if SIGWAIT_TAKES_1_ARG 10864562Sgshapiro if ((sig = sigwait(&set)) < 0) 109285229Sgshapiro#else 110157001Sgshapiro if ((sigerr = sigwait(&set, &sig)) != 0) 111285229Sgshapiro#endif 11264562Sgshapiro { 113157001Sgshapiro /* some OS return -1 and set errno: copy it */ 114157001Sgshapiro if (sigerr <= 0) 115157001Sgshapiro sigerr = errno; 116157001Sgshapiro 117110560Sgshapiro /* this can happen on OSF/1 (at least) */ 118157001Sgshapiro if (sigerr == EINTR) 119110560Sgshapiro continue; 12064562Sgshapiro smi_log(SMI_LOG_ERR, 12190792Sgshapiro "%s: sigwait returned error: %d", 122157001Sgshapiro (char *)name, sigerr); 12364562Sgshapiro if (++errs > MAX_FAILS_T) 12464562Sgshapiro { 12564562Sgshapiro mi_stop_milters(MILTER_ABRT); 12664562Sgshapiro return NULL; 12764562Sgshapiro } 12864562Sgshapiro continue; 12964562Sgshapiro } 13064562Sgshapiro errs = 0; 13164562Sgshapiro 13264562Sgshapiro switch (sig) 13364562Sgshapiro { 13464562Sgshapiro case SIGHUP: 13564562Sgshapiro case SIGTERM: 13664562Sgshapiro mi_stop_milters(MILTER_STOP); 13764562Sgshapiro return NULL; 13864562Sgshapiro case SIGINT: 13964562Sgshapiro mi_stop_milters(MILTER_ABRT); 14064562Sgshapiro return NULL; 14164562Sgshapiro default: 14264562Sgshapiro smi_log(SMI_LOG_ERR, 14364562Sgshapiro "%s: sigwait returned unmasked signal: %d", 14464562Sgshapiro (char *)name, sig); 14564562Sgshapiro break; 14664562Sgshapiro } 14764562Sgshapiro } 148120256Sgshapiro /* NOTREACHED */ 14964562Sgshapiro} 15090792Sgshapiro/* 15164562Sgshapiro** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals 15264562Sgshapiro** 15364562Sgshapiro** Parameters: 15464562Sgshapiro** name -- name of milter 15564562Sgshapiro** 15664562Sgshapiro** Returns: 15764562Sgshapiro** MI_SUCCESS/MI_FAILURE 15864562Sgshapiro*/ 15964562Sgshapiro 16064562Sgshapirostatic int 16164562Sgshapiromi_spawn_signal_thread(name) 16264562Sgshapiro char *name; 16364562Sgshapiro{ 16464562Sgshapiro sthread_t tid; 16590792Sgshapiro int r; 16664562Sgshapiro sigset_t set; 16764562Sgshapiro 16864562Sgshapiro /* Mask HUP and KILL signals */ 169120256Sgshapiro (void) sigemptyset(&set); 170120256Sgshapiro (void) sigaddset(&set, SIGHUP); 171120256Sgshapiro (void) sigaddset(&set, SIGTERM); 172120256Sgshapiro (void) sigaddset(&set, SIGINT); 17364562Sgshapiro 17464562Sgshapiro if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) 17564562Sgshapiro { 17664562Sgshapiro smi_log(SMI_LOG_ERR, 17764562Sgshapiro "%s: Couldn't mask HUP and KILL signals", name); 17864562Sgshapiro return MI_FAILURE; 17964562Sgshapiro } 18090792Sgshapiro r = thread_create(&tid, mi_signal_thread, (void *)name); 18190792Sgshapiro if (r != 0) 18264562Sgshapiro { 18364562Sgshapiro smi_log(SMI_LOG_ERR, 18490792Sgshapiro "%s: Couldn't start signal thread: %d", 18590792Sgshapiro name, r); 18664562Sgshapiro return MI_FAILURE; 18764562Sgshapiro } 18864562Sgshapiro return MI_SUCCESS; 18964562Sgshapiro} 19090792Sgshapiro/* 19164562Sgshapiro** MI_CONTROL_STARTUP -- startup for thread to handle signals 19264562Sgshapiro** 19364562Sgshapiro** Parameters: 19464562Sgshapiro** name -- name of milter 19564562Sgshapiro** 19664562Sgshapiro** Returns: 19764562Sgshapiro** MI_SUCCESS/MI_FAILURE 19864562Sgshapiro*/ 19964562Sgshapiro 20064562Sgshapiroint 20164562Sgshapiromi_control_startup(name) 20264562Sgshapiro char *name; 20364562Sgshapiro{ 20464562Sgshapiro 20564562Sgshapiro if (!smutex_init(&M_Mutex)) 20664562Sgshapiro { 20764562Sgshapiro smi_log(SMI_LOG_ERR, 20864562Sgshapiro "%s: Couldn't initialize control pipe mutex", name); 20964562Sgshapiro return MI_FAILURE; 21064562Sgshapiro } 21164562Sgshapiro 21264562Sgshapiro /* 21364562Sgshapiro ** spawn_signal_thread must happen before other threads are spawned 21464562Sgshapiro ** off so that it can mask the right signals and other threads 21564562Sgshapiro ** will inherit that mask. 21664562Sgshapiro */ 21764562Sgshapiro if (mi_spawn_signal_thread(name) == MI_FAILURE) 21864562Sgshapiro { 21964562Sgshapiro smi_log(SMI_LOG_ERR, 22064562Sgshapiro "%s: Couldn't spawn signal thread", name); 22164562Sgshapiro (void) smutex_destroy(&M_Mutex); 22264562Sgshapiro return MI_FAILURE; 22364562Sgshapiro } 22464562Sgshapiro return MI_SUCCESS; 22564562Sgshapiro} 226