xref: /onnv-gate/usr/src/lib/libast/common/misc/sigcrit.c (revision 12068:08a39a083754)
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