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 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
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
33 static struct
34 {
35 int sig;
36 int op;
37 }
38 signals[] = /* 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
70 static long hold; /* held signal mask */
71
72 /*
73 * hold last signal for later delivery
74 */
75
76 static void
interrupt(int sig)77 interrupt(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
95 int
sigcritical(int op)96 sigcritical(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