1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 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 33static struct 34{ 35 int sig; 36 int op; 37} 38signals[] = /* 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 70static long hold; /* held signal mask */ 71 72/* 73 * hold last signal for later delivery 74 */ 75 76static void 77interrupt(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 95int 96sigcritical(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