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