13 #include "ecore_private.h"
15 /* make mono happy - this is evil though... */
17 /* valgrind in some versions/setups uses SIGRT's... hmmm */
20 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
22 static void _ecore_signal_callback_set(int sig, Signal_Handler func);
23 static void _ecore_signal_callback_ignore(int sig, siginfo_t *si, void *foo);
24 static void _ecore_signal_callback_sigchld(int sig, siginfo_t *si, void *foo);
25 static void _ecore_signal_callback_sigusr1(int sig, siginfo_t *si, void *foo);
26 static void _ecore_signal_callback_sigusr2(int sig, siginfo_t *si, void *foo);
27 static void _ecore_signal_callback_sighup(int sig, siginfo_t *si, void *foo);
28 static void _ecore_signal_callback_sigquit(int sig, siginfo_t *si, void *foo);
29 static void _ecore_signal_callback_sigint(int sig, siginfo_t *si, void *foo);
30 static void _ecore_signal_callback_sigterm(int sig, siginfo_t *si, void *foo);
32 static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
36 static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
39 static Eina_Bool _ecore_signal_exe_exit_delay(void *data);
41 //#define MAXSIGQ 256 // 32k
42 #define MAXSIGQ 64 // 8k
44 static volatile sig_atomic_t sig_count = 0;
45 static volatile sig_atomic_t sigchld_count = 0;
46 static volatile sig_atomic_t sigusr1_count = 0;
47 static volatile sig_atomic_t sigusr2_count = 0;
48 static volatile sig_atomic_t sighup_count = 0;
49 static volatile sig_atomic_t sigquit_count = 0;
50 static volatile sig_atomic_t sigint_count = 0;
51 static volatile sig_atomic_t sigterm_count = 0;
53 static volatile sig_atomic_t sigpwr_count = 0;
56 static volatile sig_atomic_t *sigrt_count = NULL;
59 static volatile siginfo_t sigchld_info[MAXSIGQ];
60 static volatile siginfo_t sigusr1_info[MAXSIGQ];
61 static volatile siginfo_t sigusr2_info[MAXSIGQ];
62 static volatile siginfo_t sighup_info[MAXSIGQ];
63 static volatile siginfo_t sigquit_info[MAXSIGQ];
64 static volatile siginfo_t sigint_info[MAXSIGQ];
65 static volatile siginfo_t sigterm_info[MAXSIGQ];
67 static volatile siginfo_t sigpwr_info[MAXSIGQ];
70 static volatile siginfo_t *sigrt_info[MAXSIGQ];
74 _ecore_signal_shutdown(void)
77 int i, num = SIGRTMAX - SIGRTMIN;
80 _ecore_signal_callback_set(SIGPIPE, (Signal_Handler) SIG_DFL);
81 _ecore_signal_callback_set(SIGALRM, (Signal_Handler) SIG_DFL);
82 _ecore_signal_callback_set(SIGCHLD, (Signal_Handler) SIG_DFL);
83 _ecore_signal_callback_set(SIGUSR1, (Signal_Handler) SIG_DFL);
84 _ecore_signal_callback_set(SIGUSR2, (Signal_Handler) SIG_DFL);
85 _ecore_signal_callback_set(SIGHUP, (Signal_Handler) SIG_DFL);
86 _ecore_signal_callback_set(SIGQUIT, (Signal_Handler) SIG_DFL);
87 _ecore_signal_callback_set(SIGINT, (Signal_Handler) SIG_DFL);
88 _ecore_signal_callback_set(SIGTERM, (Signal_Handler) SIG_DFL);
90 _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
103 for (i = 0; i < num; i++)
105 _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
111 free((sig_atomic_t *) sigrt_count);
115 for (i = 0; i < MAXSIGQ; i++)
119 free((siginfo_t *) sigrt_info[i]);
120 sigrt_info[i] = NULL;
127 _ecore_signal_init(void)
130 int i, num = SIGRTMAX - SIGRTMIN;
133 _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
134 _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
135 _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
136 _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
137 _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
138 _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
139 _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
140 _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
141 _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
143 _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
147 sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
150 for (i = 0; i < MAXSIGQ; i++)
152 sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
153 assert(sigrt_info[i]);
156 for (i = 0; i < num; i++)
157 _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
162 _ecore_signal_count_get(void)
168 _ecore_signal_call(void)
171 int i, num = SIGRTMAX - SIGRTMIN;
173 volatile sig_atomic_t n;
174 sigset_t oldset, newset;
176 if (sig_count == 0) return;
177 sigemptyset(&newset);
178 sigaddset(&newset, SIGPIPE);
179 sigaddset(&newset, SIGALRM);
180 sigaddset(&newset, SIGCHLD);
181 sigaddset(&newset, SIGUSR1);
182 sigaddset(&newset, SIGUSR2);
183 sigaddset(&newset, SIGHUP);
184 sigaddset(&newset, SIGQUIT);
185 sigaddset(&newset, SIGINT);
186 sigaddset(&newset, SIGTERM);
188 sigaddset(&newset, SIGPWR);
191 for (i = 0; i < num; i++)
192 sigaddset(&newset, SIGRTMIN + i);
194 sigprocmask(SIG_BLOCK, &newset, &oldset);
195 if (sigchld_count > MAXSIGQ)
196 WRN("%i SIGCHLD in queue. max queue size %i. losing "
197 "siginfo for extra signals.", sigchld_count, MAXSIGQ);
198 for (n = 0; n < sigchld_count; n++)
203 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
205 Ecore_Exe_Event_Del *e;
207 /* FIXME: If this process is set respawn, respawn with a suitable backoff
208 * period for those that need too much respawning.
210 e = _ecore_exe_event_del_new();
213 if (WIFEXITED(status))
215 e->exit_code = WEXITSTATUS(status);
218 else if (WIFSIGNALED(status))
220 e->exit_signal = WTERMSIG(status);
224 e->exe = _ecore_exe_find(pid);
226 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
227 e->data = sigchld_info[n]; /* No need to clone this. */
229 if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
231 /* We want to report the Last Words of the exe, so delay this event.
232 * This is twice as relevant for stderr.
233 * There are three possibilities here -
234 * 1 There are no Last Words.
235 * 2 There are Last Words, they are not ready to be read.
236 * 3 There are Last Words, they are ready to be read.
238 * For 1 we don't want to delay, for 3 we want to delay.
239 * 2 is the problem. If we check for data now and there
240 * is none, then there is no way to differentiate 1 and 2.
241 * If we don't delay, we may loose data, but if we do delay,
242 * there may not be data and the exit event never gets sent.
244 * Any way you look at it, there has to be some time passed
245 * before the exit event gets sent. So the strategy here is
246 * to setup a timer event that will send the exit event after
247 * an arbitrary, but brief, time.
249 * This is probably paranoid, for the less paraniod, we could
250 * check to see for Last Words, and only delay if there are any.
251 * This has it's own set of problems.
253 Ecore_Timer *doomsday_clock;
255 doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
256 IF_FN_DEL(ecore_timer_del, doomsday_clock);
257 _ecore_exe_doomsday_clock_set(e->exe, ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e));
261 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
262 _ecore_exe_event_del_free, NULL);
270 if (sigusr1_count > MAXSIGQ)
271 WRN("%i SIGUSR1 in queue. max queue size %i. losing "
272 "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
273 for (n = 0; n < sigusr1_count; n++)
275 Ecore_Event_Signal_User *e;
277 e = _ecore_event_signal_user_new();
282 if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
283 e->data = sigusr1_info[n];
285 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
291 if (sigusr2_count > MAXSIGQ)
292 WRN("%i SIGUSR2 in queue. max queue size %i. losing "
293 "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
294 for (n = 0; n < sigusr2_count; n++)
296 Ecore_Event_Signal_User *e;
298 e = _ecore_event_signal_user_new();
303 if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
304 e->data = sigusr2_info[n];
306 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
312 if (sighup_count > MAXSIGQ)
313 WRN("%i SIGHUP in queue. max queue size %i. losing "
314 "siginfo for extra signals.", sighup_count, MAXSIGQ);
315 for (n = 0; n < sighup_count; n++)
317 Ecore_Event_Signal_Hup *e;
319 e = _ecore_event_signal_hup_new();
322 if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
323 e->data = sighup_info[n];
325 ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
331 if (sigquit_count > MAXSIGQ)
332 WRN("%i SIGQUIT in queue. max queue size %i. losing "
333 "siginfo for extra signals.", sigquit_count, MAXSIGQ);
334 for (n = 0; n < sigquit_count; n++)
336 Ecore_Event_Signal_Exit *e;
338 e = _ecore_event_signal_exit_new();
343 if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
344 e->data = sigquit_info[n];
346 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
352 if (sigint_count > MAXSIGQ)
353 WRN("%i SIGINT in queue. max queue size %i. losing "
354 "siginfo for extra signals.", sigint_count, MAXSIGQ);
355 for (n = 0; n < sigint_count; n++)
357 Ecore_Event_Signal_Exit *e;
359 e = _ecore_event_signal_exit_new();
364 if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
365 e->data = sigint_info[n];
367 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
373 if (sigterm_count > MAXSIGQ)
374 WRN("%i SIGTERM in queue. max queue size %i. losing "
375 "siginfo for extra signals.", sigterm_count, MAXSIGQ);
376 for (n = 0; n < sigterm_count; n++)
378 Ecore_Event_Signal_Exit *e;
380 e = _ecore_event_signal_exit_new();
385 if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
386 e->data = sigterm_info[n];
388 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
395 if (sigpwr_count > MAXSIGQ)
396 WRN("%i SIGPWR in queue. max queue size %i. losing "
397 "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
398 for (n = 0; n < sigpwr_count; n++)
400 Ecore_Event_Signal_Power *e;
402 e = _ecore_event_signal_power_new();
405 if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
406 e->data = sigpwr_info[n];
408 ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
416 for (i = 0; i < num; i++)
418 if (sigrt_count[i] > MAXSIGQ)
419 WRN("%i SIGRT%i in queue. max queue size %i. losing "
420 "siginfo for extra signals.", i + 1, sigrt_count[i], MAXSIGQ);
421 for (n = 0; n < sigrt_count[i]; n++)
423 Ecore_Event_Signal_Realtime *e;
425 if ((e = _ecore_event_signal_realtime_new()))
429 if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
430 e->data = sigrt_info[n][i];
432 ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
439 sigprocmask(SIG_SETMASK, &oldset, NULL);
443 _ecore_signal_callback_set(int sig, Signal_Handler func)
447 sa.sa_sigaction = func;
448 sa.sa_flags = SA_RESTART | SA_SIGINFO;
449 sigemptyset(&sa.sa_mask);
450 sigaction(sig, &sa, NULL);
454 _ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
459 _ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
461 volatile sig_atomic_t n;
466 sigchld_info[n] = *si;
468 sigchld_info[n].si_signo = 0;
476 _ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
478 volatile sig_atomic_t n;
483 sigusr1_info[n] = *si;
485 sigusr1_info[n].si_signo = 0;
492 _ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
494 volatile sig_atomic_t n;
499 sigusr2_info[n] = *si;
501 sigusr2_info[n].si_signo = 0;
508 _ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
510 volatile sig_atomic_t n;
515 sighup_info[n] = *si;
517 sighup_info[n].si_signo = 0;
524 _ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
526 volatile sig_atomic_t n;
531 sigquit_info[n] = *si;
533 sigquit_info[n].si_signo = 0;
540 _ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
542 volatile sig_atomic_t n;
547 sigint_info[n] = *si;
549 sigint_info[n].si_signo = 0;
556 _ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
558 volatile sig_atomic_t n;
563 sigterm_info[n] = *si;
565 sigterm_info[n].si_signo = 0;
573 _ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
575 volatile sig_atomic_t n;
580 sigpwr_info[n] = *si;
582 sigpwr_info[n].si_signo = 0;
591 _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
593 volatile sig_atomic_t n;
598 sigrt_info[n][sig - SIGRTMIN] = *si;
600 sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
602 sigrt_count[sig - SIGRTMIN]++;
608 _ecore_signal_exe_exit_delay(void *data)
610 Ecore_Exe_Event_Del *e;
615 _ecore_exe_doomsday_clock_set(e->exe, NULL);
616 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
617 _ecore_exe_event_del_free, NULL);
619 return ECORE_CALLBACK_CANCEL;