This source file includes following definitions.
- zend_signal_handler_defer
- zend_signal_handler_unblock
- zend_signal_handler
- zend_sigaction
- zend_signal
- zend_signal_register
- zend_signal_activate
- zend_signal_deactivate
- zend_signal_globals_ctor
- zend_signal_init
- zend_signal_startup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #define _GNU_SOURCE
31 #include <string.h>
32
33 #include "zend.h"
34 #include "zend_globals.h"
35
36 #ifdef HAVE_SIGNAL_H
37 #include <signal.h>
38 #endif
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 #ifdef ZEND_SIGNALS
45
46 #include "zend_signal.h"
47
48 #ifdef ZTS
49 ZEND_API int zend_signal_globals_id;
50 #else
51 zend_signal_globals_t zend_signal_globals;
52 #endif
53
54 static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context);
55 static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*));
56
57 #ifdef __CYGWIN__
58 #define TIMEOUT_SIG SIGALRM
59 #else
60 #define TIMEOUT_SIG SIGPROF
61 #endif
62
63 static int zend_sigs[] = { TIMEOUT_SIG, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2 };
64
65 #define SA_FLAGS_MASK ~(SA_NODEFER | SA_RESETHAND)
66
67
68 static zend_signal_entry_t global_orig_handlers[NSIG];
69 static sigset_t global_sigmask;
70
71
72
73 void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
74 {
75 int errno_save = errno;
76 zend_signal_queue_t *queue, *qtmp;
77
78 #ifdef ZTS
79 ZEND_TSRMLS_CACHE_UPDATE();
80 #endif
81
82 if (EXPECTED(SIGG(active))) {
83 if (UNEXPECTED(SIGG(depth) == 0)) {
84 if (UNEXPECTED(SIGG(blocked))) {
85 SIGG(blocked) = 0;
86 }
87 if (EXPECTED(SIGG(running) == 0)) {
88 SIGG(running) = 1;
89 zend_signal_handler(signo, siginfo, context);
90
91 queue = SIGG(phead);
92 SIGG(phead) = NULL;
93
94 while (queue) {
95 zend_signal_handler(queue->zend_signal.signo, queue->zend_signal.siginfo, queue->zend_signal.context);
96 qtmp = queue->next;
97 queue->next = SIGG(pavail);
98 queue->zend_signal.signo = 0;
99 SIGG(pavail) = queue;
100 queue = qtmp;
101 }
102 SIGG(running) = 0;
103 }
104 } else {
105 SIGG(blocked) = 1;
106
107 if ((queue = SIGG(pavail))) {
108 SIGG(pavail) = queue->next;
109 queue->zend_signal.signo = signo;
110 queue->zend_signal.siginfo = siginfo;
111 queue->zend_signal.context = context;
112 queue->next = NULL;
113
114 if (SIGG(phead) && SIGG(ptail)) {
115 SIGG(ptail)->next = queue;
116 } else {
117 SIGG(phead) = queue;
118 }
119 SIGG(ptail) = queue;
120 }
121 #if ZEND_DEBUG
122 else {
123 zend_output_debug_string(0, "zend_signal: not enough queue storage, lost signal (%d)", signo);
124 }
125 #endif
126 }
127 } else {
128
129 zend_signal_handler(signo, siginfo, context);
130 }
131
132 errno = errno_save;
133 }
134
135
136
137 ZEND_API void zend_signal_handler_unblock(void)
138 {
139 zend_signal_queue_t *queue;
140 zend_signal_t zend_signal;
141
142 if (EXPECTED(SIGG(active))) {
143 SIGNAL_BEGIN_CRITICAL();
144 queue = SIGG(phead);
145 SIGG(phead) = queue->next;
146 zend_signal = queue->zend_signal;
147 queue->next = SIGG(pavail);
148 queue->zend_signal.signo = 0;
149 SIGG(pavail) = queue;
150
151 zend_signal_handler_defer(zend_signal.signo, zend_signal.siginfo, zend_signal.context);
152 SIGNAL_END_CRITICAL();
153 }
154 }
155
156
157
158
159
160 static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context)
161 {
162 int errno_save = errno;
163 struct sigaction sa = {{0}};
164 sigset_t sigset;
165 zend_signal_entry_t p_sig = SIGG(handlers)[signo-1];
166
167 if (p_sig.handler == SIG_DFL) {
168 if (sigaction(signo, NULL, &sa) == 0) {
169 sa.sa_handler = SIG_DFL;
170 sigemptyset(&sa.sa_mask);
171
172 sigemptyset(&sigset);
173 sigaddset(&sigset, signo);
174
175 if (sigaction(signo, &sa, NULL) == 0) {
176
177 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
178 raise(signo);
179 }
180 }
181 } else if (p_sig.handler != SIG_IGN) {
182 if (p_sig.flags & SA_SIGINFO) {
183 if (p_sig.flags & SA_RESETHAND) {
184 SIGG(handlers)[signo-1].flags = 0;
185 SIGG(handlers)[signo-1].handler = SIG_DFL;
186 }
187 (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
188 } else {
189 (*(void (*)(int))p_sig.handler)(signo);
190 }
191 }
192
193 errno = errno_save;
194 }
195
196
197
198 ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact)
199 {
200 struct sigaction sa = {{0}};
201 sigset_t sigset;
202
203 if (oldact != NULL) {
204 oldact->sa_flags = SIGG(handlers)[signo-1].flags;
205 oldact->sa_handler = (void *) SIGG(handlers)[signo-1].handler;
206 oldact->sa_mask = global_sigmask;
207 }
208 if (act != NULL) {
209 SIGG(handlers)[signo-1].flags = act->sa_flags;
210 if (act->sa_flags & SA_SIGINFO) {
211 SIGG(handlers)[signo-1].handler = (void *) act->sa_sigaction;
212 } else {
213 SIGG(handlers)[signo-1].handler = (void *) act->sa_handler;
214 }
215
216 sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
217 sa.sa_sigaction = zend_signal_handler_defer;
218 sa.sa_mask = global_sigmask;
219
220 if (sigaction(signo, &sa, NULL) < 0) {
221 zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);
222 }
223
224
225 sigemptyset(&sigset);
226 sigaddset(&sigset, signo);
227 zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
228 }
229
230 return SUCCESS;
231 }
232
233
234
235
236 ZEND_API int zend_signal(int signo, void (*handler)(int))
237 {
238 struct sigaction sa = {{0}};
239
240 sa.sa_flags = 0;
241 sa.sa_handler = handler;
242 sa.sa_mask = global_sigmask;
243
244 return zend_sigaction(signo, &sa, NULL);
245 }
246
247
248
249
250
251
252 static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*))
253 {
254 struct sigaction sa = {{0}};
255
256 if (sigaction(signo, NULL, &sa) == 0) {
257 if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction == handler) {
258 return FAILURE;
259 }
260
261 SIGG(handlers)[signo-1].flags = sa.sa_flags;
262 if (sa.sa_flags & SA_SIGINFO) {
263 SIGG(handlers)[signo-1].handler = (void *)sa.sa_sigaction;
264 } else {
265 SIGG(handlers)[signo-1].handler = (void *)sa.sa_handler;
266 }
267
268 sa.sa_flags = SA_SIGINFO;
269 sa.sa_sigaction = handler;
270 sa.sa_mask = global_sigmask;
271
272 if (sigaction(signo, &sa, NULL) < 0) {
273 zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);
274 }
275
276 return SUCCESS;
277 }
278 return FAILURE;
279 }
280
281
282
283 void zend_signal_activate(void)
284 {
285 int x;
286
287 memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
288
289 for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
290 zend_signal_register(zend_sigs[x], zend_signal_handler_defer);
291 }
292
293 SIGG(active) = 1;
294 SIGG(depth) = 0;
295 }
296
297
298
299 void zend_signal_deactivate(void)
300 {
301
302 if (SIGG(check)) {
303 int x;
304 struct sigaction sa = {{0}};
305 if (SIGG(depth) != 0) {
306 zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
307 }
308
309 for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
310 sigaction(zend_sigs[x], NULL, &sa);
311 if (sa.sa_sigaction != zend_signal_handler_defer) {
312 zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
313 }
314 }
315 }
316
317 SIGNAL_BEGIN_CRITICAL();
318 SIGG(active) = 0;
319 SIGG(running) = 0;
320 SIGG(blocked) = 0;
321 SIGG(depth) = 0;
322 SIGNAL_END_CRITICAL();
323 }
324
325
326 static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals)
327 {
328 size_t x;
329
330 memset(zend_signal_globals, 0, sizeof(*zend_signal_globals));
331
332 for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) {
333 zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x];
334 queue->zend_signal.signo = 0;
335 queue->next = zend_signal_globals->pavail;
336 zend_signal_globals->pavail = queue;
337 }
338 }
339
340
341 void zend_signal_init()
342 {
343 int signo;
344 struct sigaction sa = {{0}};
345
346
347 memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
348 for (signo = 1; signo < NSIG; ++signo) {
349 if (sigaction(signo, NULL, &sa) == 0) {
350 global_orig_handlers[signo-1].flags = sa.sa_flags;
351 if (sa.sa_flags & SA_SIGINFO) {
352 global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
353 } else {
354 global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
355 }
356 }
357 }
358 }
359
360
361
362
363 void zend_signal_startup()
364 {
365
366 #ifdef ZTS
367 ts_allocate_id(&zend_signal_globals_id, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, NULL);
368 #else
369 zend_signal_globals_ctor(&zend_signal_globals);
370 #endif
371
372
373 sigfillset(&global_sigmask);
374 sigdelset(&global_sigmask, SIGILL);
375 sigdelset(&global_sigmask, SIGABRT);
376 sigdelset(&global_sigmask, SIGFPE);
377 sigdelset(&global_sigmask, SIGKILL);
378 sigdelset(&global_sigmask, SIGSEGV);
379 sigdelset(&global_sigmask, SIGCONT);
380 sigdelset(&global_sigmask, SIGSTOP);
381 sigdelset(&global_sigmask, SIGTSTP);
382 sigdelset(&global_sigmask, SIGTTIN);
383 sigdelset(&global_sigmask, SIGTTOU);
384 #ifdef SIGBUS
385 sigdelset(&global_sigmask, SIGBUS);
386 #endif
387 #ifdef SIGSYS
388 sigdelset(&global_sigmask, SIGSYS);
389 #endif
390 #ifdef SIGTRAP
391 sigdelset(&global_sigmask, SIGTRAP);
392 #endif
393
394 zend_signal_init();
395 }
396
397
398
399 #endif
400
401
402
403
404
405
406
407
408
409