signal.c revision 132943
1/* 2 * Copyright (c) 1999-2003 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.41 2003/11/19 00:25:20 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 (void) sigemptyset(&set); 94 (void) sigaddset(&set, SIGHUP); 95 (void) sigaddset(&set, SIGTERM); 96 97 /* Handle Ctrl-C gracefully for debugging */ 98 (void) sigaddset(&set, SIGINT); 99 errs = 0; 100 101 for (;;) 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 /* this can happen on OSF/1 (at least) */ 111 if (errno == EINTR) 112 continue; 113 smi_log(SMI_LOG_ERR, 114 "%s: sigwait returned error: %d", 115 (char *)name, errno); 116 if (++errs > MAX_FAILS_T) 117 { 118 mi_stop_milters(MILTER_ABRT); 119 return NULL; 120 } 121 continue; 122 } 123 errs = 0; 124 125 switch (sig) 126 { 127 case SIGHUP: 128 case SIGTERM: 129 mi_stop_milters(MILTER_STOP); 130 return NULL; 131 case SIGINT: 132 mi_stop_milters(MILTER_ABRT); 133 return NULL; 134 default: 135 smi_log(SMI_LOG_ERR, 136 "%s: sigwait returned unmasked signal: %d", 137 (char *)name, sig); 138 break; 139 } 140 } 141 /* NOTREACHED */ 142} 143/* 144** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals 145** 146** Parameters: 147** name -- name of milter 148** 149** Returns: 150** MI_SUCCESS/MI_FAILURE 151*/ 152 153static int 154mi_spawn_signal_thread(name) 155 char *name; 156{ 157 sthread_t tid; 158 int r; 159 sigset_t set; 160 161 /* Mask HUP and KILL signals */ 162 (void) sigemptyset(&set); 163 (void) sigaddset(&set, SIGHUP); 164 (void) sigaddset(&set, SIGTERM); 165 (void) sigaddset(&set, SIGINT); 166 167 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) 168 { 169 smi_log(SMI_LOG_ERR, 170 "%s: Couldn't mask HUP and KILL signals", name); 171 return MI_FAILURE; 172 } 173 r = thread_create(&tid, mi_signal_thread, (void *)name); 174 if (r != 0) 175 { 176 smi_log(SMI_LOG_ERR, 177 "%s: Couldn't start signal thread: %d", 178 name, r); 179 return MI_FAILURE; 180 } 181 return MI_SUCCESS; 182} 183/* 184** MI_CONTROL_STARTUP -- startup for thread to handle signals 185** 186** Parameters: 187** name -- name of milter 188** 189** Returns: 190** MI_SUCCESS/MI_FAILURE 191*/ 192 193int 194mi_control_startup(name) 195 char *name; 196{ 197 198 if (!smutex_init(&M_Mutex)) 199 { 200 smi_log(SMI_LOG_ERR, 201 "%s: Couldn't initialize control pipe mutex", name); 202 return MI_FAILURE; 203 } 204 205 /* 206 ** spawn_signal_thread must happen before other threads are spawned 207 ** off so that it can mask the right signals and other threads 208 ** will inherit that mask. 209 */ 210 if (mi_spawn_signal_thread(name) == MI_FAILURE) 211 { 212 smi_log(SMI_LOG_ERR, 213 "%s: Couldn't spawn signal thread", name); 214 (void) smutex_destroy(&M_Mutex); 215 return MI_FAILURE; 216 } 217 return MI_SUCCESS; 218} 219