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_globals_dtor
- zend_signal_startup
- zend_signal_shutdown
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 TSRMLS_DC);
55 static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC);
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 TSRMLS_FETCH();
78
79 if (SIGG(active)) {
80 if (SIGG(depth) == 0) {
81 if (SIGG(blocked) != -1) {
82 SIGG(blocked) = -1;
83 }
84 if (SIGG(running) == 0) {
85 SIGG(running) = 1;
86 zend_signal_handler(signo, siginfo, context TSRMLS_CC);
87
88 queue = SIGG(phead);
89 SIGG(phead) = NULL;
90
91 while (queue) {
92 zend_signal_handler(queue->zend_signal.signo, queue->zend_signal.siginfo, queue->zend_signal.context TSRMLS_CC);
93 qtmp = queue->next;
94 queue->next = SIGG(pavail);
95 queue->zend_signal.signo = 0;
96 SIGG(pavail) = queue;
97 queue = qtmp;
98 }
99 SIGG(running) = 0;
100 }
101 } else {
102 SIGG(blocked) = 0;
103
104 if ((queue = SIGG(pavail))) {
105 SIGG(pavail) = queue->next;
106 queue->zend_signal.signo = signo;
107 queue->zend_signal.siginfo = siginfo;
108 queue->zend_signal.context = context;
109 queue->next = NULL;
110
111 if (SIGG(phead) && SIGG(ptail)) {
112 SIGG(ptail)->next = queue;
113 } else {
114 SIGG(phead) = queue;
115 }
116 SIGG(ptail) = queue;
117 }
118 #if ZEND_DEBUG
119 else {
120 zend_output_debug_string(0, "zend_signal: not enough queue storage, lost signal (%d)", signo);
121 }
122 #endif
123 }
124 } else {
125
126 zend_signal_handler(signo, siginfo, context TSRMLS_CC);
127 }
128
129 errno = errno_save;
130 }
131
132
133
134 ZEND_API void zend_signal_handler_unblock(TSRMLS_D)
135 {
136 zend_signal_queue_t *queue;
137 zend_signal_t zend_signal;
138
139 if (SIGG(active)) {
140 SIGNAL_BEGIN_CRITICAL();
141 queue = SIGG(phead);
142 SIGG(phead) = queue->next;
143 zend_signal = queue->zend_signal;
144 queue->next = SIGG(pavail);
145 queue->zend_signal.signo = 0;
146 SIGG(pavail) = queue;
147
148 zend_signal_handler_defer(zend_signal.signo, zend_signal.siginfo, zend_signal.context);
149 SIGNAL_END_CRITICAL();
150 }
151 }
152
153
154
155
156
157 static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context TSRMLS_DC)
158 {
159 int errno_save = errno;
160 struct sigaction sa = {{0}};
161 sigset_t sigset;
162 zend_signal_entry_t p_sig = SIGG(handlers)[signo-1];
163
164 if (p_sig.handler == SIG_DFL) {
165 if (sigaction(signo, NULL, &sa) == 0) {
166 sa.sa_handler = SIG_DFL;
167 sigemptyset(&sa.sa_mask);
168
169 sigemptyset(&sigset);
170 sigaddset(&sigset, signo);
171
172 if (sigaction(signo, &sa, NULL) == 0) {
173
174 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
175 raise(signo);
176 }
177 }
178 } else if (p_sig.handler != SIG_IGN) {
179 if (p_sig.flags & SA_SIGINFO) {
180 if (p_sig.flags & SA_RESETHAND) {
181 SIGG(handlers)[signo-1].flags = 0;
182 SIGG(handlers)[signo-1].handler = SIG_DFL;
183 }
184 (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
185 } else {
186 (*(void (*)(int))p_sig.handler)(signo);
187 }
188 }
189
190 errno = errno_save;
191 }
192
193
194
195 ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact TSRMLS_DC)
196 {
197 struct sigaction sa = {{0}};
198 sigset_t sigset;
199
200 if (oldact != NULL) {
201 oldact->sa_flags = SIGG(handlers)[signo-1].flags;
202 oldact->sa_handler = (void *) SIGG(handlers)[signo-1].handler;
203 oldact->sa_mask = global_sigmask;
204 }
205 if (act != NULL) {
206 SIGG(handlers)[signo-1].flags = act->sa_flags;
207 if (act->sa_flags & SA_SIGINFO) {
208 SIGG(handlers)[signo-1].handler = (void *) act->sa_sigaction;
209 } else {
210 SIGG(handlers)[signo-1].handler = (void *) act->sa_handler;
211 }
212
213 sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
214 sa.sa_sigaction = zend_signal_handler_defer;
215 sa.sa_mask = global_sigmask;
216
217 if (sigaction(signo, &sa, NULL) < 0) {
218 zend_error(E_ERROR, "Error installing signal handler for %d", signo);
219 }
220
221
222 sigemptyset(&sigset);
223 sigaddset(&sigset, signo);
224 zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
225 }
226
227 return SUCCESS;
228 }
229
230
231
232
233 ZEND_API int zend_signal(int signo, void (*handler)(int) TSRMLS_DC)
234 {
235 struct sigaction sa = {{0}};
236
237 sa.sa_flags = 0;
238 sa.sa_handler = handler;
239 sa.sa_mask = global_sigmask;
240
241 return zend_sigaction(signo, &sa, NULL TSRMLS_CC);
242 }
243
244
245
246
247
248
249 static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC)
250 {
251 struct sigaction sa = {{0}};
252
253 if (sigaction(signo, NULL, &sa) == 0) {
254 if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction == handler) {
255 return FAILURE;
256 }
257
258 SIGG(handlers)[signo-1].flags = sa.sa_flags;
259 if (sa.sa_flags & SA_SIGINFO) {
260 SIGG(handlers)[signo-1].handler = (void *)sa.sa_sigaction;
261 } else {
262 SIGG(handlers)[signo-1].handler = (void *)sa.sa_handler;
263 }
264
265 sa.sa_flags = SA_SIGINFO;
266 sa.sa_sigaction = handler;
267 sa.sa_mask = global_sigmask;
268
269 if (sigaction(signo, &sa, NULL) < 0) {
270 zend_error(E_ERROR, "Error installing signal handler for %d", signo);
271 }
272
273 return SUCCESS;
274 }
275 return FAILURE;
276 }
277
278
279
280 void zend_signal_activate(TSRMLS_D)
281 {
282 int x;
283
284 memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
285
286 for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
287 zend_signal_register(zend_sigs[x], zend_signal_handler_defer TSRMLS_CC);
288 }
289
290 SIGG(active) = 1;
291 SIGG(depth) = 0;
292 }
293
294
295
296 void zend_signal_deactivate(TSRMLS_D)
297 {
298 int x;
299 struct sigaction sa = {{0}};
300
301 if (SIGG(check)) {
302 if (SIGG(depth) != 0) {
303 zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
304 }
305
306 for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
307 sigaction(zend_sigs[x], NULL, &sa);
308 if (sa.sa_sigaction != zend_signal_handler_defer) {
309 zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
310 }
311 }
312 }
313
314 SIGNAL_BEGIN_CRITICAL();
315 SIGG(active) = 0;
316 SIGG(running) = 0;
317 SIGG(blocked) = -1;
318 SIGG(depth) = 0;
319 SIGNAL_END_CRITICAL();
320 }
321
322
323 static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals TSRMLS_DC)
324 {
325 size_t x;
326
327 memset(zend_signal_globals, 0, sizeof(*zend_signal_globals));
328 zend_signal_globals->blocked = -1;
329
330 for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) {
331 zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x];
332 queue->zend_signal.signo = 0;
333 queue->next = zend_signal_globals->pavail;
334 zend_signal_globals->pavail = queue;
335 }
336 }
337
338 static void zend_signal_globals_dtor(zend_signal_globals_t *zend_signal_globals TSRMLS_DC)
339 {
340 zend_signal_globals->blocked = -1;
341 }
342
343
344
345 void zend_signal_startup()
346 {
347 int signo;
348 struct sigaction sa = {{0}};
349
350 #ifdef ZTS
351 ts_allocate_id(&zend_signal_globals_id, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, (ts_allocate_dtor) zend_signal_globals_dtor);
352 #else
353 zend_signal_globals_ctor(&zend_signal_globals);
354 #endif
355
356
357 sigfillset(&global_sigmask);
358 sigdelset(&global_sigmask, SIGILL);
359 sigdelset(&global_sigmask, SIGABRT);
360 sigdelset(&global_sigmask, SIGFPE);
361 sigdelset(&global_sigmask, SIGKILL);
362 sigdelset(&global_sigmask, SIGSEGV);
363 sigdelset(&global_sigmask, SIGCONT);
364 sigdelset(&global_sigmask, SIGSTOP);
365 sigdelset(&global_sigmask, SIGTSTP);
366 sigdelset(&global_sigmask, SIGTTIN);
367 sigdelset(&global_sigmask, SIGTTOU);
368 #ifdef SIGBUS
369 sigdelset(&global_sigmask, SIGBUS);
370 #endif
371 #ifdef SIGSYS
372 sigdelset(&global_sigmask, SIGSYS);
373 #endif
374 #ifdef SIGTRAP
375 sigdelset(&global_sigmask, SIGTRAP);
376 #endif
377
378
379 memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
380 for (signo = 1; signo < NSIG; ++signo) {
381 if (sigaction(signo, NULL, &sa) == 0) {
382 global_orig_handlers[signo-1].flags = sa.sa_flags;
383 if (sa.sa_flags & SA_SIGINFO) {
384 global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
385 } else {
386 global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
387 }
388 }
389 }
390 }
391
392
393
394
395 void zend_signal_shutdown(TSRMLS_D)
396 {
397 #ifndef ZTS
398 zend_signal_globals_dtor(&zend_signal_globals);
399 #endif
400 }
401
402
403
404 #endif
405
406
407
408
409
410
411
412
413
414