2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
10 #include <sys/types.h>
17 #include "ecore_private.h"
19 /* make mono happy - this is evil though... */
21 /* valgrind in some versions/setups uses SIGRT's... hmmm */
24 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
26 static void _ecore_signal_callback_set(int sig, Signal_Handler func);
27 static void _ecore_signal_callback_ignore(int sig, siginfo_t *si, void *foo);
28 static void _ecore_signal_callback_sigchld(int sig, siginfo_t *si, void *foo);
29 static void _ecore_signal_callback_sigusr1(int sig, siginfo_t *si, void *foo);
30 static void _ecore_signal_callback_sigusr2(int sig, siginfo_t *si, void *foo);
31 static void _ecore_signal_callback_sighup(int sig, siginfo_t *si, void *foo);
32 static void _ecore_signal_callback_sigquit(int sig, siginfo_t *si, void *foo);
33 static void _ecore_signal_callback_sigint(int sig, siginfo_t *si, void *foo);
34 static void _ecore_signal_callback_sigterm(int sig, siginfo_t *si, void *foo);
36 static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
40 static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
43 static int _ecore_signal_exe_exit_delay(void *data);
45 //#define MAXSIGQ 256 // 32k
46 #define MAXSIGQ 64 // 8k
48 static volatile sig_atomic_t sig_count = 0;
49 static volatile sig_atomic_t sigchld_count = 0;
50 static volatile sig_atomic_t sigusr1_count = 0;
51 static volatile sig_atomic_t sigusr2_count = 0;
52 static volatile sig_atomic_t sighup_count = 0;
53 static volatile sig_atomic_t sigquit_count = 0;
54 static volatile sig_atomic_t sigint_count = 0;
55 static volatile sig_atomic_t sigterm_count = 0;
57 static volatile sig_atomic_t sigpwr_count = 0;
60 static volatile sig_atomic_t *sigrt_count = NULL;
63 static volatile siginfo_t sigchld_info[MAXSIGQ];
64 static volatile siginfo_t sigusr1_info[MAXSIGQ];
65 static volatile siginfo_t sigusr2_info[MAXSIGQ];
66 static volatile siginfo_t sighup_info[MAXSIGQ];
67 static volatile siginfo_t sigquit_info[MAXSIGQ];
68 static volatile siginfo_t sigint_info[MAXSIGQ];
69 static volatile siginfo_t sigterm_info[MAXSIGQ];
71 static volatile siginfo_t sigpwr_info[MAXSIGQ];
74 static volatile siginfo_t *sigrt_info[MAXSIGQ];
78 _ecore_signal_shutdown(void)
81 int i, num = SIGRTMAX - SIGRTMIN;
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);
94 _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
107 for (i = 0; i < num; i++)
109 _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
115 free((sig_atomic_t *) sigrt_count);
119 for (i = 0; i < MAXSIGQ; i++)
123 free((siginfo_t *) sigrt_info[i]);
124 sigrt_info[i] = NULL;
131 _ecore_signal_init(void)
134 int i, num = SIGRTMAX - SIGRTMIN;
137 _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
138 _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
139 _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
140 _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
141 _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
142 _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
143 _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
144 _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
145 _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
147 _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
151 sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
154 for (i = 0; i < MAXSIGQ; i++)
156 sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
157 assert(sigrt_info[i]);
160 for (i = 0; i < num; i++)
161 _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
166 _ecore_signal_count_get(void)
172 _ecore_signal_call(void)
175 int i, num = SIGRTMAX - SIGRTMIN;
177 volatile sig_atomic_t n;
178 sigset_t oldset, newset;
180 if (sig_count == 0) return;
181 sigemptyset(&newset);
182 sigaddset(&newset, SIGPIPE);
183 sigaddset(&newset, SIGALRM);
184 sigaddset(&newset, SIGCHLD);
185 sigaddset(&newset, SIGUSR1);
186 sigaddset(&newset, SIGUSR2);
187 sigaddset(&newset, SIGHUP);
188 sigaddset(&newset, SIGQUIT);
189 sigaddset(&newset, SIGINT);
190 sigaddset(&newset, SIGTERM);
192 sigaddset(&newset, SIGPWR);
195 for (i = 0; i < num; i++)
196 sigaddset(&newset, SIGRTMIN + i);
198 sigprocmask(SIG_BLOCK, &newset, &oldset);
199 if (sigchld_count > MAXSIGQ)
200 WRN("%i SIGCHLD in queue. max queue size %i. losing "
201 "siginfo for extra signals.", sigchld_count, MAXSIGQ);
202 for (n = 0; n < sigchld_count; n++)
207 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
209 Ecore_Exe_Event_Del *e;
211 /* FIXME: If this process is set respawn, respawn with a suitable backoff
212 * period for those that need too much respawning.
214 e = _ecore_exe_event_del_new();
217 if (WIFEXITED(status))
219 e->exit_code = WEXITSTATUS(status);
222 else if (WIFSIGNALED(status))
224 e->exit_signal = WTERMSIG(status);
228 e->exe = _ecore_exe_find(pid);
230 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
231 e->data = sigchld_info[n]; /* No need to clone this. */
233 if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
235 /* We want to report the Last Words of the exe, so delay this event.
236 * This is twice as relevant for stderr.
237 * There are three possibilities here -
238 * 1 There are no Last Words.
239 * 2 There are Last Words, they are not ready to be read.
240 * 3 There are Last Words, they are ready to be read.
242 * For 1 we don't want to delay, for 3 we want to delay.
243 * 2 is the problem. If we check for data now and there
244 * is none, then there is no way to differentiate 1 and 2.
245 * If we don't delay, we may loose data, but if we do delay,
246 * there may not be data and the exit event never gets sent.
248 * Any way you look at it, there has to be some time passed
249 * before the exit event gets sent. So the strategy here is
250 * to setup a timer event that will send the exit event after
251 * an arbitrary, but brief, time.
253 * This is probably paranoid, for the less paraniod, we could
254 * check to see for Last Words, and only delay if there are any.
255 * This has it's own set of problems.
257 Ecore_Timer *doomsday_clock;
259 doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
260 IF_FN_DEL(ecore_timer_del, doomsday_clock);
261 _ecore_exe_doomsday_clock_set(e->exe, ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e));
265 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
266 _ecore_exe_event_del_free, NULL);
274 if (sigusr1_count > MAXSIGQ)
275 WRN("%i SIGUSR1 in queue. max queue size %i. losing "
276 "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
277 for (n = 0; n < sigusr1_count; n++)
279 Ecore_Event_Signal_User *e;
281 e = _ecore_event_signal_user_new();
286 if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
287 e->data = sigusr1_info[n];
289 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
295 if (sigusr2_count > MAXSIGQ)
296 WRN("%i SIGUSR2 in queue. max queue size %i. losing "
297 "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
298 for (n = 0; n < sigusr2_count; n++)
300 Ecore_Event_Signal_User *e;
302 e = _ecore_event_signal_user_new();
307 if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
308 e->data = sigusr2_info[n];
310 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
316 if (sighup_count > MAXSIGQ)
317 WRN("%i SIGHUP in queue. max queue size %i. losing "
318 "siginfo for extra signals.", sighup_count, MAXSIGQ);
319 for (n = 0; n < sighup_count; n++)
321 Ecore_Event_Signal_Hup *e;
323 e = _ecore_event_signal_hup_new();
326 if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
327 e->data = sighup_info[n];
329 ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
335 if (sigquit_count > MAXSIGQ)
336 WRN("%i SIGQUIT in queue. max queue size %i. losing "
337 "siginfo for extra signals.", sigquit_count, MAXSIGQ);
338 for (n = 0; n < sigquit_count; n++)
340 Ecore_Event_Signal_Exit *e;
342 e = _ecore_event_signal_exit_new();
347 if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
348 e->data = sigquit_info[n];
350 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
356 if (sigint_count > MAXSIGQ)
357 WRN("%i SIGINT in queue. max queue size %i. losing "
358 "siginfo for extra signals.", sigint_count, MAXSIGQ);
359 for (n = 0; n < sigint_count; n++)
361 Ecore_Event_Signal_Exit *e;
363 e = _ecore_event_signal_exit_new();
368 if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
369 e->data = sigint_info[n];
371 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
377 if (sigterm_count > MAXSIGQ)
378 WRN("%i SIGTERM in queue. max queue size %i. losing "
379 "siginfo for extra signals.", sigterm_count, MAXSIGQ);
380 for (n = 0; n < sigterm_count; n++)
382 Ecore_Event_Signal_Exit *e;
384 e = _ecore_event_signal_exit_new();
389 if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
390 e->data = sigterm_info[n];
392 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
399 if (sigpwr_count > MAXSIGQ)
400 WRN("%i SIGPWR in queue. max queue size %i. losing "
401 "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
402 for (n = 0; n < sigpwr_count; n++)
404 Ecore_Event_Signal_Power *e;
406 e = _ecore_event_signal_power_new();
409 if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
410 e->data = sigpwr_info[n];
412 ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
420 for (i = 0; i < num; i++)
422 if (sigrt_count[i] > MAXSIGQ)
423 WRN("%i SIGRT%i in queue. max queue size %i. losing "
424 "siginfo for extra signals.", i + 1, sigrt_count[i], MAXSIGQ);
425 for (n = 0; n < sigrt_count[i]; n++)
427 Ecore_Event_Signal_Realtime *e;
429 if ((e = _ecore_event_signal_realtime_new()))
433 if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
434 e->data = sigrt_info[n][i];
436 ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
443 sigprocmask(SIG_SETMASK, &oldset, NULL);
447 _ecore_signal_callback_set(int sig, Signal_Handler func)
451 sa.sa_sigaction = func;
452 sa.sa_flags = SA_RESTART | SA_SIGINFO;
453 sigemptyset(&sa.sa_mask);
454 sigaction(sig, &sa, NULL);
458 _ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
463 _ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
465 volatile sig_atomic_t n;
470 sigchld_info[n] = *si;
472 sigchld_info[n].si_signo = 0;
480 _ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
482 volatile sig_atomic_t n;
487 sigusr1_info[n] = *si;
489 sigusr1_info[n].si_signo = 0;
496 _ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
498 volatile sig_atomic_t n;
503 sigusr2_info[n] = *si;
505 sigusr2_info[n].si_signo = 0;
512 _ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
514 volatile sig_atomic_t n;
519 sighup_info[n] = *si;
521 sighup_info[n].si_signo = 0;
528 _ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
530 volatile sig_atomic_t n;
535 sigquit_info[n] = *si;
537 sigquit_info[n].si_signo = 0;
544 _ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
546 volatile sig_atomic_t n;
551 sigint_info[n] = *si;
553 sigint_info[n].si_signo = 0;
560 _ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
562 volatile sig_atomic_t n;
567 sigterm_info[n] = *si;
569 sigterm_info[n].si_signo = 0;
577 _ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
579 volatile sig_atomic_t n;
584 sigpwr_info[n] = *si;
586 sigpwr_info[n].si_signo = 0;
595 _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
597 volatile sig_atomic_t n;
602 sigrt_info[n][sig - SIGRTMIN] = *si;
604 sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
606 sigrt_count[sig - SIGRTMIN]++;
612 _ecore_signal_exe_exit_delay(void *data)
614 Ecore_Exe_Event_Del *e;
619 _ecore_exe_doomsday_clock_set(e->exe, NULL);
620 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
621 _ecore_exe_event_del_free, NULL);