signal.c revision 90792
1/* 2 * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11#include <sm/gen.h> 12SM_RCSID("@(#)$Id: signal.c,v 8.35 2002/01/10 01:34:55 ca Exp $") 13 14#include "libmilter.h" 15 16/* 17** thread to handle signals 18*/ 19 20static smutex_t M_Mutex; 21 22static int MilterStop = MILTER_CONT; 23 24/* 25** MI_STOP -- return value of MilterStop 26** 27** Parameters: 28** none. 29** 30** Returns: 31** value of MilterStop 32*/ 33 34int 35mi_stop() 36{ 37 return MilterStop; 38} 39/* 40** MI_STOP_MILTERS -- set value of MilterStop 41** 42** Parameters: 43** v -- new value for MilterStop. 44** 45** Returns: 46** none. 47*/ 48 49void 50mi_stop_milters(v) 51 int v; 52{ 53 (void) smutex_lock(&M_Mutex); 54 if (MilterStop < v) 55 MilterStop = v; 56 57 /* close listen socket */ 58 mi_closener(); 59 (void) smutex_unlock(&M_Mutex); 60} 61/* 62** MI_CLEAN_SIGNALS -- clean up signal handler thread 63** 64** Parameters: 65** none. 66** 67** Returns: 68** none. 69*/ 70 71void 72mi_clean_signals() 73{ 74 (void) smutex_destroy(&M_Mutex); 75} 76/* 77** MI_SIGNAL_THREAD -- thread to deal with signals 78** 79** Parameters: 80** name -- name of milter 81** 82** Returns: 83** NULL 84*/ 85 86static void * 87mi_signal_thread(name) 88 void *name; 89{ 90 int sig, errs; 91 sigset_t set; 92 93 sigemptyset(&set); 94 sigaddset(&set, SIGHUP); 95 sigaddset(&set, SIGTERM); 96 97 /* Handle Ctrl-C gracefully for debugging */ 98 sigaddset(&set, SIGINT); 99 errs = 0; 100 101 while (true) 102 { 103 sig = 0; 104#if defined(SOLARIS) || defined(__svr5__) 105 if ((sig = sigwait(&set)) < 0) 106#else /* defined(SOLARIS) || defined(__svr5__) */ 107 if (sigwait(&set, &sig) != 0) 108#endif /* defined(SOLARIS) || defined(__svr5__) */ 109 { 110 smi_log(SMI_LOG_ERR, 111 "%s: sigwait returned error: %d", 112 (char *)name, errno); 113 if (++errs > MAX_FAILS_T) 114 { 115 mi_stop_milters(MILTER_ABRT); 116 return NULL; 117 } 118 continue; 119 } 120 errs = 0; 121 122 switch (sig) 123 { 124 case SIGHUP: 125 case SIGTERM: 126 mi_stop_milters(MILTER_STOP); 127 return NULL; 128 case SIGINT: 129 mi_stop_milters(MILTER_ABRT); 130 return NULL; 131 default: 132 smi_log(SMI_LOG_ERR, 133 "%s: sigwait returned unmasked signal: %d", 134 (char *)name, sig); 135 break; 136 } 137 } 138} 139/* 140** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals 141** 142** Parameters: 143** name -- name of milter 144** 145** Returns: 146** MI_SUCCESS/MI_FAILURE 147*/ 148 149static int 150mi_spawn_signal_thread(name) 151 char *name; 152{ 153 sthread_t tid; 154 int r; 155 sigset_t set; 156 157 /* Mask HUP and KILL signals */ 158 sigemptyset(&set); 159 sigaddset(&set, SIGHUP); 160 sigaddset(&set, SIGTERM); 161 sigaddset(&set, SIGINT); 162 163 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) 164 { 165 smi_log(SMI_LOG_ERR, 166 "%s: Couldn't mask HUP and KILL signals", name); 167 return MI_FAILURE; 168 } 169 r = thread_create(&tid, mi_signal_thread, (void *)name); 170 if (r != 0) 171 { 172 smi_log(SMI_LOG_ERR, 173 "%s: Couldn't start signal thread: %d", 174 name, r); 175 return MI_FAILURE; 176 } 177 return MI_SUCCESS; 178} 179/* 180** MI_CONTROL_STARTUP -- startup for thread to handle signals 181** 182** Parameters: 183** name -- name of milter 184** 185** Returns: 186** MI_SUCCESS/MI_FAILURE 187*/ 188 189int 190mi_control_startup(name) 191 char *name; 192{ 193 194 if (!smutex_init(&M_Mutex)) 195 { 196 smi_log(SMI_LOG_ERR, 197 "%s: Couldn't initialize control pipe mutex", name); 198 return MI_FAILURE; 199 } 200 201 /* 202 ** spawn_signal_thread must happen before other threads are spawned 203 ** off so that it can mask the right signals and other threads 204 ** will inherit that mask. 205 */ 206 if (mi_spawn_signal_thread(name) == MI_FAILURE) 207 { 208 smi_log(SMI_LOG_ERR, 209 "%s: Couldn't spawn signal thread", name); 210 (void) smutex_destroy(&M_Mutex); 211 return MI_FAILURE; 212 } 213 return MI_SUCCESS; 214} 215