aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore/ecore_signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_signal.c')
-rw-r--r--libraries/ecore/src/lib/ecore/ecore_signal.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_signal.c b/libraries/ecore/src/lib/ecore/ecore_signal.c
new file mode 100644
index 0000000..78edb8c
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore/ecore_signal.c
@@ -0,0 +1,565 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/wait.h>
8#include <signal.h>
9#include <unistd.h>
10#include <assert.h>
11
12#include "Ecore.h"
13#include "ecore_private.h"
14
15/* make mono happy - this is evil though... */
16#undef SIGPWR
17/* valgrind in some versions/setups uses SIGRT's... hmmm */
18
19typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
20
21static void _ecore_signal_callback_set(int sig,
22 Signal_Handler func);
23static void _ecore_signal_callback_ignore(int sig,
24 siginfo_t *si,
25 void *foo);
26static void _ecore_signal_callback_sigchld(int sig,
27 siginfo_t *si,
28 void *foo);
29static void _ecore_signal_callback_sigusr1(int sig,
30 siginfo_t *si,
31 void *foo);
32static void _ecore_signal_callback_sigusr2(int sig,
33 siginfo_t *si,
34 void *foo);
35static void _ecore_signal_callback_sighup(int sig,
36 siginfo_t *si,
37 void *foo);
38static void _ecore_signal_callback_sigquit(int sig,
39 siginfo_t *si,
40 void *foo);
41static void _ecore_signal_callback_sigint(int sig,
42 siginfo_t *si,
43 void *foo);
44static void _ecore_signal_callback_sigterm(int sig,
45 siginfo_t *si,
46 void *foo);
47#ifdef SIGPWR
48static void _ecore_signal_callback_sigpwr(int sig,
49 siginfo_t *si,
50 void *foo);
51#endif
52
53static Eina_Bool _ecore_signal_exe_exit_delay(void *data);
54
55//#define MAXSIGQ 256 // 32k
56#define MAXSIGQ 64 // 8k
57
58static volatile sig_atomic_t sig_count = 0;
59static volatile sig_atomic_t sigchld_count = 0;
60static volatile sig_atomic_t sigusr1_count = 0;
61static volatile sig_atomic_t sigusr2_count = 0;
62static volatile sig_atomic_t sighup_count = 0;
63static volatile sig_atomic_t sigquit_count = 0;
64static volatile sig_atomic_t sigint_count = 0;
65static volatile sig_atomic_t sigterm_count = 0;
66#ifdef SIGPWR
67static volatile sig_atomic_t sigpwr_count = 0;
68#endif
69
70static volatile siginfo_t sigchld_info[MAXSIGQ];
71static volatile siginfo_t sigusr1_info[MAXSIGQ];
72static volatile siginfo_t sigusr2_info[MAXSIGQ];
73static volatile siginfo_t sighup_info[MAXSIGQ];
74static volatile siginfo_t sigquit_info[MAXSIGQ];
75static volatile siginfo_t sigint_info[MAXSIGQ];
76static volatile siginfo_t sigterm_info[MAXSIGQ];
77#ifdef SIGPWR
78static volatile siginfo_t sigpwr_info[MAXSIGQ];
79#endif
80
81void
82_ecore_signal_shutdown(void)
83{
84 _ecore_signal_callback_set(SIGPIPE, (Signal_Handler)SIG_DFL);
85 _ecore_signal_callback_set(SIGALRM, (Signal_Handler)SIG_DFL);
86 _ecore_signal_callback_set(SIGCHLD, (Signal_Handler)SIG_DFL);
87 _ecore_signal_callback_set(SIGUSR1, (Signal_Handler)SIG_DFL);
88 _ecore_signal_callback_set(SIGUSR2, (Signal_Handler)SIG_DFL);
89 _ecore_signal_callback_set(SIGHUP, (Signal_Handler)SIG_DFL);
90 _ecore_signal_callback_set(SIGQUIT, (Signal_Handler)SIG_DFL);
91 _ecore_signal_callback_set(SIGINT, (Signal_Handler)SIG_DFL);
92 _ecore_signal_callback_set(SIGTERM, (Signal_Handler)SIG_DFL);
93#ifdef SIGPWR
94 _ecore_signal_callback_set(SIGPWR, (Signal_Handler)SIG_DFL);
95 sigpwr_count = 0;
96#endif
97 sigchld_count = 0;
98 sigusr1_count = 0;
99 sigusr2_count = 0;
100 sighup_count = 0;
101 sigquit_count = 0;
102 sigint_count = 0;
103 sigterm_count = 0;
104 sig_count = 0;
105}
106
107void
108_ecore_signal_init(void)
109{
110 _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
111 _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
112 _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
113 _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
114 _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
115 _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
116 _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
117 _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
118 _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
119#ifdef SIGPWR
120 _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
121#endif
122}
123
124void
125_ecore_signal_received_process(void)
126{
127 while (_ecore_signal_count_get()) _ecore_signal_call();
128}
129
130int
131_ecore_signal_count_get(void)
132{
133 return sig_count;
134}
135
136void
137_ecore_signal_call(void)
138{
139 volatile sig_atomic_t n;
140 sigset_t oldset, newset;
141
142 if (sig_count == 0) return;
143 sigemptyset(&newset);
144 sigaddset(&newset, SIGPIPE);
145 sigaddset(&newset, SIGALRM);
146 sigaddset(&newset, SIGCHLD);
147 sigaddset(&newset, SIGUSR1);
148 sigaddset(&newset, SIGUSR2);
149 sigaddset(&newset, SIGHUP);
150 sigaddset(&newset, SIGQUIT);
151 sigaddset(&newset, SIGINT);
152 sigaddset(&newset, SIGTERM);
153#ifdef SIGPWR
154 sigaddset(&newset, SIGPWR);
155#endif
156 sigprocmask(SIG_BLOCK, &newset, &oldset);
157 if (sigchld_count > MAXSIGQ)
158 WRN("%i SIGCHLD in queue. max queue size %i. losing "
159 "siginfo for extra signals.", sigchld_count, MAXSIGQ);
160 for (n = 0; n < sigchld_count; n++)
161 {
162 pid_t pid;
163 int status;
164
165 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
166 {
167 Ecore_Exe_Event_Del *e;
168
169 /* FIXME: If this process is set respawn, respawn with a suitable backoff
170 * period for those that need too much respawning.
171 */
172 e = _ecore_exe_event_del_new();
173 if (e)
174 {
175 if (WIFEXITED(status))
176 {
177 e->exit_code = WEXITSTATUS(status);
178 e->exited = 1;
179 }
180 else if (WIFSIGNALED(status))
181 {
182 e->exit_signal = WTERMSIG(status);
183 e->signalled = 1;
184 }
185 e->pid = pid;
186 e->exe = _ecore_exe_find(pid);
187
188 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
189 e->data = sigchld_info[n]; /* No need to clone this. */
190
191 if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
192 {
193 /* We want to report the Last Words of the exe, so delay this event.
194 * This is twice as relevant for stderr.
195 * There are three possibilities here -
196 * 1 There are no Last Words.
197 * 2 There are Last Words, they are not ready to be read.
198 * 3 There are Last Words, they are ready to be read.
199 *
200 * For 1 we don't want to delay, for 3 we want to delay.
201 * 2 is the problem. If we check for data now and there
202 * is none, then there is no way to differentiate 1 and 2.
203 * If we don't delay, we may loose data, but if we do delay,
204 * there may not be data and the exit event never gets sent.
205 *
206 * Any way you look at it, there has to be some time passed
207 * before the exit event gets sent. So the strategy here is
208 * to setup a timer event that will send the exit event after
209 * an arbitrary, but brief, time.
210 *
211 * This is probably paranoid, for the less paraniod, we could
212 * check to see for Last Words, and only delay if there are any.
213 * This has it's own set of problems.
214 */
215 Ecore_Timer *doomsday_clock;
216
217 doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
218 IF_FN_DEL(ecore_timer_del, doomsday_clock);
219 _ecore_unlock();
220 doomsday_clock = ecore_timer_add
221 (0.1, _ecore_signal_exe_exit_delay, e);
222 _ecore_lock();
223 _ecore_exe_doomsday_clock_set(e->exe, doomsday_clock);
224 }
225 else
226 {
227 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
228 _ecore_exe_event_del_free, NULL);
229 }
230 }
231 }
232 sig_count--;
233 }
234 sigchld_count = 0;
235
236 if (sigusr1_count > MAXSIGQ)
237 WRN("%i SIGUSR1 in queue. max queue size %i. losing "
238 "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
239 for (n = 0; n < sigusr1_count; n++)
240 {
241 Ecore_Event_Signal_User *e;
242
243 e = _ecore_event_signal_user_new();
244 if (e)
245 {
246 e->number = 1;
247
248 if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
249 e->data = sigusr1_info[n];
250
251 _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
252 }
253 sig_count--;
254 }
255 sigusr1_count = 0;
256
257 if (sigusr2_count > MAXSIGQ)
258 WRN("%i SIGUSR2 in queue. max queue size %i. losing "
259 "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
260 for (n = 0; n < sigusr2_count; n++)
261 {
262 Ecore_Event_Signal_User *e;
263
264 e = _ecore_event_signal_user_new();
265 if (e)
266 {
267 e->number = 2;
268
269 if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
270 e->data = sigusr2_info[n];
271
272 _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
273 }
274 sig_count--;
275 }
276 sigusr2_count = 0;
277
278 if (sighup_count > MAXSIGQ)
279 WRN("%i SIGHUP in queue. max queue size %i. losing "
280 "siginfo for extra signals.", sighup_count, MAXSIGQ);
281 for (n = 0; n < sighup_count; n++)
282 {
283 Ecore_Event_Signal_Hup *e;
284
285 e = _ecore_event_signal_hup_new();
286 if (e)
287 {
288 if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
289 e->data = sighup_info[n];
290
291 _ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
292 }
293 sig_count--;
294 }
295 sighup_count = 0;
296
297 if (sigquit_count > MAXSIGQ)
298 WRN("%i SIGQUIT in queue. max queue size %i. losing "
299 "siginfo for extra signals.", sigquit_count, MAXSIGQ);
300 for (n = 0; n < sigquit_count; n++)
301 {
302 Ecore_Event_Signal_Exit *e;
303
304 e = _ecore_event_signal_exit_new();
305 if (e)
306 {
307 e->quit = 1;
308
309 if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
310 e->data = sigquit_info[n];
311
312 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
313 }
314 sig_count--;
315 }
316 sigquit_count = 0;
317
318 if (sigint_count > MAXSIGQ)
319 WRN("%i SIGINT in queue. max queue size %i. losing "
320 "siginfo for extra signals.", sigint_count, MAXSIGQ);
321 for (n = 0; n < sigint_count; n++)
322 {
323 Ecore_Event_Signal_Exit *e;
324
325 e = _ecore_event_signal_exit_new();
326 if (e)
327 {
328 e->interrupt = 1;
329
330 if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
331 e->data = sigint_info[n];
332
333 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
334 }
335 sig_count--;
336 }
337 sigint_count = 0;
338
339 if (sigterm_count > MAXSIGQ)
340 WRN("%i SIGTERM in queue. max queue size %i. losing "
341 "siginfo for extra signals.", sigterm_count, MAXSIGQ);
342 for (n = 0; n < sigterm_count; n++)
343 {
344 Ecore_Event_Signal_Exit *e;
345
346 e = _ecore_event_signal_exit_new();
347 if (e)
348 {
349 e->terminate = 1;
350
351 if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
352 e->data = sigterm_info[n];
353
354 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
355 }
356 sig_count--;
357 }
358 sigterm_count = 0;
359
360#ifdef SIGPWR
361 if (sigpwr_count > MAXSIGQ)
362 WRN("%i SIGPWR in queue. max queue size %i. losing "
363 "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
364 for (n = 0; n < sigpwr_count; n++)
365 {
366 Ecore_Event_Signal_Power *e;
367
368 e = _ecore_event_signal_power_new();
369 if (e)
370 {
371 if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
372 e->data = sigpwr_info[n];
373
374 _ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
375 }
376 sig_count--;
377 }
378 sigpwr_count = 0;
379#endif
380
381 sigprocmask(SIG_SETMASK, &oldset, NULL);
382}
383
384static void
385_ecore_signal_callback_set(int sig,
386 Signal_Handler func)
387{
388 struct sigaction sa;
389
390 sa.sa_sigaction = func;
391 sa.sa_flags = SA_RESTART | SA_SIGINFO;
392 sigemptyset(&sa.sa_mask);
393 sigaction(sig, &sa, NULL);
394}
395
396static void
397_ecore_signal_callback_ignore(int sig __UNUSED__,
398 siginfo_t *si __UNUSED__,
399 void *foo __UNUSED__)
400{
401}
402
403static void
404_ecore_signal_callback_sigchld(int sig __UNUSED__,
405 siginfo_t *si,
406 void *foo __UNUSED__)
407{
408 volatile sig_atomic_t n;
409 n = sigchld_count;
410 if (n < MAXSIGQ)
411 {
412 if (si)
413 sigchld_info[n] = *si;
414 else
415 sigchld_info[n].si_signo = 0;
416 }
417
418 sigchld_count++;
419 sig_count++;
420}
421
422static void
423_ecore_signal_callback_sigusr1(int sig __UNUSED__,
424 siginfo_t *si,
425 void *foo __UNUSED__)
426{
427 volatile sig_atomic_t n;
428 n = sigusr1_count;
429 if (n < MAXSIGQ)
430 {
431 if (si)
432 sigusr1_info[n] = *si;
433 else
434 sigusr1_info[n].si_signo = 0;
435 }
436 sigusr1_count++;
437 sig_count++;
438}
439
440static void
441_ecore_signal_callback_sigusr2(int sig __UNUSED__,
442 siginfo_t *si,
443 void *foo __UNUSED__)
444{
445 volatile sig_atomic_t n;
446 n = sigusr2_count;
447 if (n < MAXSIGQ)
448 {
449 if (si)
450 sigusr2_info[n] = *si;
451 else
452 sigusr2_info[n].si_signo = 0;
453 }
454 sigusr2_count++;
455 sig_count++;
456}
457
458static void
459_ecore_signal_callback_sighup(int sig __UNUSED__,
460 siginfo_t *si,
461 void *foo __UNUSED__)
462{
463 volatile sig_atomic_t n;
464 n = sighup_count;
465 if (n < MAXSIGQ)
466 {
467 if (si)
468 sighup_info[n] = *si;
469 else
470 sighup_info[n].si_signo = 0;
471 }
472 sighup_count++;
473 sig_count++;
474}
475
476static void
477_ecore_signal_callback_sigquit(int sig __UNUSED__,
478 siginfo_t *si,
479 void *foo __UNUSED__)
480{
481 volatile sig_atomic_t n;
482 n = sigquit_count;
483 if (n < MAXSIGQ)
484 {
485 if (si)
486 sigquit_info[n] = *si;
487 else
488 sigquit_info[n].si_signo = 0;
489 }
490 sigquit_count++;
491 sig_count++;
492}
493
494static void
495_ecore_signal_callback_sigint(int sig __UNUSED__,
496 siginfo_t *si,
497 void *foo __UNUSED__)
498{
499 volatile sig_atomic_t n;
500 n = sigint_count;
501 if (n < MAXSIGQ)
502 {
503 if (si)
504 sigint_info[n] = *si;
505 else
506 sigint_info[n].si_signo = 0;
507 }
508 sigint_count++;
509 sig_count++;
510}
511
512static void
513_ecore_signal_callback_sigterm(int sig __UNUSED__,
514 siginfo_t *si,
515 void *foo __UNUSED__)
516{
517 volatile sig_atomic_t n;
518 n = sigterm_count;
519 if (n < MAXSIGQ)
520 {
521 if (si)
522 sigterm_info[n] = *si;
523 else
524 sigterm_info[n].si_signo = 0;
525 }
526 sigterm_count++;
527 sig_count++;
528}
529
530#ifdef SIGPWR
531static void
532_ecore_signal_callback_sigpwr(int sig __UNUSED__,
533 siginfo_t *si,
534 void *foo __UNUSED__)
535{
536 volatile sig_atomic_t n;
537 n = sigpwr_count;
538 if (n < MAXSIGQ)
539 {
540 if (si)
541 sigpwr_info[n] = *si;
542 else
543 sigpwr_info[n].si_signo = 0;
544 }
545 sigpwr_count++;
546 sig_count++;
547}
548
549#endif
550
551static Eina_Bool
552_ecore_signal_exe_exit_delay(void *data)
553{
554 Ecore_Exe_Event_Del *e;
555
556 e = data;
557 if (e)
558 {
559 _ecore_exe_doomsday_clock_set(e->exe, NULL);
560 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
561 _ecore_exe_event_del_free, NULL);
562 }
563 return ECORE_CALLBACK_CANCEL;
564}
565