1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #pragma prototyped 23*4887Schin /* 24*4887Schin * Glenn Fowler 25*4887Schin * AT&T Research 26*4887Schin * 27*4887Schin * signal critical region support 28*4887Schin */ 29*4887Schin 30*4887Schin #include <ast.h> 31*4887Schin #include <sig.h> 32*4887Schin 33*4887Schin static struct 34*4887Schin { 35*4887Schin int sig; 36*4887Schin int op; 37*4887Schin } 38*4887Schin signals[] = /* held inside critical region */ 39*4887Schin { 40*4887Schin SIGINT, SIG_REG_EXEC, 41*4887Schin #ifdef SIGPIPE 42*4887Schin SIGPIPE, SIG_REG_EXEC, 43*4887Schin #endif 44*4887Schin #ifdef SIGQUIT 45*4887Schin SIGQUIT, SIG_REG_EXEC, 46*4887Schin #endif 47*4887Schin #ifdef SIGHUP 48*4887Schin SIGHUP, SIG_REG_EXEC, 49*4887Schin #endif 50*4887Schin #if defined(SIGCHLD) && ( !defined(SIGCLD) || SIGCHLD != SIGCLD || _lib_sigprocmask || _lib_sigsetmask ) 51*4887Schin SIGCHLD, SIG_REG_PROC, 52*4887Schin #endif 53*4887Schin #ifdef SIGTSTP 54*4887Schin SIGTSTP, SIG_REG_TERM, 55*4887Schin #endif 56*4887Schin #ifdef SIGTTIN 57*4887Schin SIGTTIN, SIG_REG_TERM, 58*4887Schin #endif 59*4887Schin #ifdef SIGTTOU 60*4887Schin SIGTTOU, SIG_REG_TERM, 61*4887Schin #endif 62*4887Schin }; 63*4887Schin 64*4887Schin #ifndef SIG_SETMASK 65*4887Schin #undef _lib_sigprocmask 66*4887Schin #endif 67*4887Schin 68*4887Schin #if !_lib_sigprocmask && !_lib_sigsetmask 69*4887Schin 70*4887Schin static long hold; /* held signal mask */ 71*4887Schin 72*4887Schin /* 73*4887Schin * hold last signal for later delivery 74*4887Schin */ 75*4887Schin 76*4887Schin static void 77*4887Schin interrupt(int sig) 78*4887Schin { 79*4887Schin signal(sig, interrupt); 80*4887Schin hold |= sigmask(sig); 81*4887Schin } 82*4887Schin 83*4887Schin #endif 84*4887Schin 85*4887Schin /* 86*4887Schin * critical signal region handler 87*4887Schin * 88*4887Schin * op>0 new region according to SIG_REG_*, return region level 89*4887Schin * op==0 pop region, return region level 90*4887Schin * op<0 return non-zero if any signals held in current region 91*4887Schin * 92*4887Schin * signals[] held until region popped 93*4887Schin */ 94*4887Schin 95*4887Schin int 96*4887Schin sigcritical(int op) 97*4887Schin { 98*4887Schin register int i; 99*4887Schin static int region; 100*4887Schin static int level; 101*4887Schin #if _lib_sigprocmask 102*4887Schin static sigset_t mask; 103*4887Schin sigset_t nmask; 104*4887Schin #else 105*4887Schin #if _lib_sigsetmask 106*4887Schin static long mask; 107*4887Schin #else 108*4887Schin static Sig_handler_t handler[elementsof(signals)]; 109*4887Schin #endif 110*4887Schin #endif 111*4887Schin 112*4887Schin if (op > 0) 113*4887Schin { 114*4887Schin if (!level++) 115*4887Schin { 116*4887Schin region = op; 117*4887Schin if (op & SIG_REG_SET) 118*4887Schin level--; 119*4887Schin #if _lib_sigprocmask 120*4887Schin sigemptyset(&nmask); 121*4887Schin for (i = 0; i < elementsof(signals); i++) 122*4887Schin if (op & signals[i].op) 123*4887Schin sigaddset(&nmask, signals[i].sig); 124*4887Schin sigprocmask(SIG_BLOCK, &nmask, &mask); 125*4887Schin #else 126*4887Schin #if _lib_sigsetmask 127*4887Schin mask = 0; 128*4887Schin for (i = 0; i < elementsof(signals); i++) 129*4887Schin if (op & signals[i].op) 130*4887Schin mask |= sigmask(signals[i].sig); 131*4887Schin mask = sigblock(mask); 132*4887Schin #else 133*4887Schin hold = 0; 134*4887Schin for (i = 0; i < elementsof(signals); i++) 135*4887Schin if ((op & signals[i].op) && (handler[i] = signal(signals[i].sig, interrupt)) == SIG_IGN) 136*4887Schin { 137*4887Schin signal(signals[i].sig, handler[i]); 138*4887Schin hold &= ~sigmask(signals[i].sig); 139*4887Schin } 140*4887Schin #endif 141*4887Schin #endif 142*4887Schin } 143*4887Schin return level; 144*4887Schin } 145*4887Schin else if (op < 0) 146*4887Schin { 147*4887Schin #if _lib_sigprocmask 148*4887Schin sigpending(&nmask); 149*4887Schin for (i = 0; i < elementsof(signals); i++) 150*4887Schin if (region & signals[i].op) 151*4887Schin { 152*4887Schin if (sigismember(&nmask, signals[i].sig)) 153*4887Schin return 1; 154*4887Schin } 155*4887Schin return 0; 156*4887Schin #else 157*4887Schin #if _lib_sigsetmask 158*4887Schin /* no way to get pending signals without installing handler */ 159*4887Schin return 0; 160*4887Schin #else 161*4887Schin return hold != 0; 162*4887Schin #endif 163*4887Schin #endif 164*4887Schin } 165*4887Schin else 166*4887Schin { 167*4887Schin /* 168*4887Schin * a vfork() may have intervened so we 169*4887Schin * allow apparent nesting mismatches 170*4887Schin */ 171*4887Schin 172*4887Schin if (--level <= 0) 173*4887Schin { 174*4887Schin level = 0; 175*4887Schin #if _lib_sigprocmask 176*4887Schin sigprocmask(SIG_SETMASK, &mask, NiL); 177*4887Schin #else 178*4887Schin #if _lib_sigsetmask 179*4887Schin sigsetmask(mask); 180*4887Schin #else 181*4887Schin for (i = 0; i < elementsof(signals); i++) 182*4887Schin if (region & signals[i].op) 183*4887Schin signal(signals[i].sig, handler[i]); 184*4887Schin if (hold) 185*4887Schin { 186*4887Schin for (i = 0; i < elementsof(signals); i++) 187*4887Schin if (region & signals[i].op) 188*4887Schin { 189*4887Schin if (hold & sigmask(signals[i].sig)) 190*4887Schin kill(getpid(), signals[i].sig); 191*4887Schin } 192*4887Schin pause(); 193*4887Schin } 194*4887Schin #endif 195*4887Schin #endif 196*4887Schin } 197*4887Schin return level; 198*4887Schin } 199*4887Schin } 200