14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.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
interrupt(int sig)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
sigcritical(int op)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