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