14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * Glenn Fowler 254887Schin * AT&T Research 264887Schin * 274887Schin * signal critical region support 284887Schin */ 294887Schin 304887Schin #include <ast.h> 314887Schin #include <sig.h> 324887Schin 334887Schin static struct 344887Schin { 354887Schin int sig; 364887Schin int op; 374887Schin } 384887Schin signals[] = /* held inside critical region */ 394887Schin { 404887Schin SIGINT, SIG_REG_EXEC, 414887Schin #ifdef SIGPIPE 424887Schin SIGPIPE, SIG_REG_EXEC, 434887Schin #endif 444887Schin #ifdef SIGQUIT 454887Schin SIGQUIT, SIG_REG_EXEC, 464887Schin #endif 474887Schin #ifdef SIGHUP 484887Schin SIGHUP, SIG_REG_EXEC, 494887Schin #endif 504887Schin #if defined(SIGCHLD) && ( !defined(SIGCLD) || SIGCHLD != SIGCLD || _lib_sigprocmask || _lib_sigsetmask ) 514887Schin SIGCHLD, SIG_REG_PROC, 524887Schin #endif 534887Schin #ifdef SIGTSTP 544887Schin SIGTSTP, SIG_REG_TERM, 554887Schin #endif 564887Schin #ifdef SIGTTIN 574887Schin SIGTTIN, SIG_REG_TERM, 584887Schin #endif 594887Schin #ifdef SIGTTOU 604887Schin SIGTTOU, SIG_REG_TERM, 614887Schin #endif 624887Schin }; 634887Schin 644887Schin #ifndef SIG_SETMASK 654887Schin #undef _lib_sigprocmask 664887Schin #endif 674887Schin 684887Schin #if !_lib_sigprocmask && !_lib_sigsetmask 694887Schin 704887Schin static long hold; /* held signal mask */ 714887Schin 724887Schin /* 734887Schin * hold last signal for later delivery 744887Schin */ 754887Schin 764887Schin static void 774887Schin interrupt(int sig) 784887Schin { 794887Schin signal(sig, interrupt); 804887Schin hold |= sigmask(sig); 814887Schin } 824887Schin 834887Schin #endif 844887Schin 854887Schin /* 864887Schin * critical signal region handler 874887Schin * 884887Schin * op>0 new region according to SIG_REG_*, return region level 894887Schin * op==0 pop region, return region level 904887Schin * op<0 return non-zero if any signals held in current region 914887Schin * 924887Schin * signals[] held until region popped 934887Schin */ 944887Schin 954887Schin int 964887Schin sigcritical(int op) 974887Schin { 984887Schin register int i; 994887Schin static int region; 1004887Schin static int level; 1014887Schin #if _lib_sigprocmask 1024887Schin static sigset_t mask; 1034887Schin sigset_t nmask; 1044887Schin #else 1054887Schin #if _lib_sigsetmask 1064887Schin static long mask; 1074887Schin #else 1084887Schin static Sig_handler_t handler[elementsof(signals)]; 1094887Schin #endif 1104887Schin #endif 1114887Schin 1124887Schin if (op > 0) 1134887Schin { 1144887Schin if (!level++) 1154887Schin { 1164887Schin region = op; 1174887Schin if (op & SIG_REG_SET) 1184887Schin level--; 1194887Schin #if _lib_sigprocmask 1204887Schin sigemptyset(&nmask); 1214887Schin for (i = 0; i < elementsof(signals); i++) 1224887Schin if (op & signals[i].op) 1234887Schin sigaddset(&nmask, signals[i].sig); 1244887Schin sigprocmask(SIG_BLOCK, &nmask, &mask); 1254887Schin #else 1264887Schin #if _lib_sigsetmask 1274887Schin mask = 0; 1284887Schin for (i = 0; i < elementsof(signals); i++) 1294887Schin if (op & signals[i].op) 1304887Schin mask |= sigmask(signals[i].sig); 1314887Schin mask = sigblock(mask); 1324887Schin #else 1334887Schin hold = 0; 1344887Schin for (i = 0; i < elementsof(signals); i++) 1354887Schin if ((op & signals[i].op) && (handler[i] = signal(signals[i].sig, interrupt)) == SIG_IGN) 1364887Schin { 1374887Schin signal(signals[i].sig, handler[i]); 1384887Schin hold &= ~sigmask(signals[i].sig); 1394887Schin } 1404887Schin #endif 1414887Schin #endif 1424887Schin } 1434887Schin return level; 1444887Schin } 1454887Schin else if (op < 0) 1464887Schin { 1474887Schin #if _lib_sigprocmask 1484887Schin sigpending(&nmask); 1494887Schin for (i = 0; i < elementsof(signals); i++) 1504887Schin if (region & signals[i].op) 1514887Schin { 1524887Schin if (sigismember(&nmask, signals[i].sig)) 1534887Schin return 1; 1544887Schin } 1554887Schin return 0; 1564887Schin #else 1574887Schin #if _lib_sigsetmask 1584887Schin /* no way to get pending signals without installing handler */ 1594887Schin return 0; 1604887Schin #else 1614887Schin return hold != 0; 1624887Schin #endif 1634887Schin #endif 1644887Schin } 1654887Schin else 1664887Schin { 1674887Schin /* 1684887Schin * a vfork() may have intervened so we 1694887Schin * allow apparent nesting mismatches 1704887Schin */ 1714887Schin 1724887Schin if (--level <= 0) 1734887Schin { 1744887Schin level = 0; 1754887Schin #if _lib_sigprocmask 1764887Schin sigprocmask(SIG_SETMASK, &mask, NiL); 1774887Schin #else 1784887Schin #if _lib_sigsetmask 1794887Schin sigsetmask(mask); 1804887Schin #else 1814887Schin for (i = 0; i < elementsof(signals); i++) 1824887Schin if (region & signals[i].op) 1834887Schin signal(signals[i].sig, handler[i]); 1844887Schin if (hold) 1854887Schin { 1864887Schin for (i = 0; i < elementsof(signals); i++) 1874887Schin if (region & signals[i].op) 1884887Schin { 1894887Schin if (hold & sigmask(signals[i].sig)) 1904887Schin kill(getpid(), signals[i].sig); 1914887Schin } 1924887Schin pause(); 1934887Schin } 1944887Schin #endif 1954887Schin #endif 1964887Schin } 1974887Schin return level; 1984887Schin } 1994887Schin } 200