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