13 #include "ecore_private.h"
15 /* make mono happy - this is evil though... */
17 /* valgrind in some versions/setups uses SIGRT's... hmmm */
19 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
21 static void _ecore_signal_callback_set(int sig,
23 static void _ecore_signal_callback_ignore(int sig,
26 static void _ecore_signal_callback_sigchld(int sig,
29 static void _ecore_signal_callback_sigusr1(int sig,
32 static void _ecore_signal_callback_sigusr2(int sig,
35 static void _ecore_signal_callback_sighup(int sig,
38 static void _ecore_signal_callback_sigquit(int sig,
41 static void _ecore_signal_callback_sigint(int sig,
44 static void _ecore_signal_callback_sigterm(int sig,
48 static void _ecore_signal_callback_sigpwr(int sig,
53 static Eina_Bool _ecore_signal_exe_exit_delay(void *data);
55 //#define MAXSIGQ 256 // 32k
56 #define MAXSIGQ 64 // 8k
58 static volatile sig_atomic_t sig_count = 0;
59 static volatile sig_atomic_t sigchld_count = 0;
60 static volatile sig_atomic_t sigusr1_count = 0;
61 static volatile sig_atomic_t sigusr2_count = 0;
62 static volatile sig_atomic_t sighup_count = 0;
63 static volatile sig_atomic_t sigquit_count = 0;
64 static volatile sig_atomic_t sigint_count = 0;
65 static volatile sig_atomic_t sigterm_count = 0;
67 static volatile sig_atomic_t sigpwr_count = 0;
70 static volatile siginfo_t sigchld_info[MAXSIGQ];
71 static volatile siginfo_t sigusr1_info[MAXSIGQ];
72 static volatile siginfo_t sigusr2_info[MAXSIGQ];
73 static volatile siginfo_t sighup_info[MAXSIGQ];
74 static volatile siginfo_t sigquit_info[MAXSIGQ];
75 static volatile siginfo_t sigint_info[MAXSIGQ];
76 static volatile siginfo_t sigterm_info[MAXSIGQ];
78 static volatile siginfo_t sigpwr_info[MAXSIGQ];
82 _ecore_signal_shutdown(void)
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);
108 _ecore_signal_init(void)
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);
120 _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
125 _ecore_signal_received_process(void)
127 while (_ecore_signal_count_get()) _ecore_signal_call();
131 _ecore_signal_count_get(void)
137 _ecore_signal_generic_free(void *data __UNUSED__,
144 _ecore_signal_call(void)
146 volatile sig_atomic_t n;
147 sigset_t oldset, newset;
150 if (sig_count == 0) return;
151 sigemptyset(&newset);
152 sigaddset(&newset, SIGPIPE);
153 sigaddset(&newset, SIGALRM);
154 sigaddset(&newset, SIGCHLD);
155 sigaddset(&newset, SIGUSR1);
156 sigaddset(&newset, SIGUSR2);
157 sigaddset(&newset, SIGHUP);
158 sigaddset(&newset, SIGQUIT);
159 sigaddset(&newset, SIGINT);
160 sigaddset(&newset, SIGTERM);
162 sigaddset(&newset, SIGPWR);
164 sigprocmask(SIG_BLOCK, &newset, &oldset);
165 if (sigchld_count > MAXSIGQ)
166 WRN("%i SIGCHLD in queue. max queue size %i. losing "
167 "siginfo for extra signals.", sigchld_count, MAXSIGQ);
168 tot = sigchld_count + sigusr1_count + sigusr2_count +
169 sighup_count + sigquit_count + sigint_count + sigterm_count
175 if (sig_count != tot)
177 ERR("sig_count (%i) != actual totals (%i) ", sig_count, tot);
181 for (n = 0; n < sigchld_count; n++)
186 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
188 Ecore_Exe_Event_Del *e;
190 /* FIXME: If this process is set respawn, respawn with a suitable backoff
191 * period for those that need too much respawning.
193 e = _ecore_exe_event_del_new();
196 if (WIFEXITED(status))
198 e->exit_code = WEXITSTATUS(status);
201 else if (WIFSIGNALED(status))
203 e->exit_signal = WTERMSIG(status);
207 e->exe = _ecore_exe_find(pid);
209 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
210 e->data = sigchld_info[n]; /* No need to clone this. */
212 if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
214 /* We want to report the Last Words of the exe, so delay this event.
215 * This is twice as relevant for stderr.
216 * There are three possibilities here -
217 * 1 There are no Last Words.
218 * 2 There are Last Words, they are not ready to be read.
219 * 3 There are Last Words, they are ready to be read.
221 * For 1 we don't want to delay, for 3 we want to delay.
222 * 2 is the problem. If we check for data now and there
223 * is none, then there is no way to differentiate 1 and 2.
224 * If we don't delay, we may loose data, but if we do delay,
225 * there may not be data and the exit event never gets sent.
227 * Any way you look at it, there has to be some time passed
228 * before the exit event gets sent. So the strategy here is
229 * to setup a timer event that will send the exit event after
230 * an arbitrary, but brief, time.
232 * This is probably paranoid, for the less paraniod, we could
233 * check to see for Last Words, and only delay if there are any.
234 * This has it's own set of problems.
236 Ecore_Timer *doomsday_clock;
238 doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
239 IF_FN_DEL(ecore_timer_del, doomsday_clock);
241 doomsday_clock = ecore_timer_add
242 (0.1, _ecore_signal_exe_exit_delay, e);
244 _ecore_exe_doomsday_clock_set(e->exe, doomsday_clock);
248 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
249 _ecore_exe_event_del_free, NULL);
257 if (sigusr1_count > MAXSIGQ)
258 WRN("%i SIGUSR1 in queue. max queue size %i. losing "
259 "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
260 for (n = 0; n < sigusr1_count; n++)
262 Ecore_Event_Signal_User *e;
264 e = _ecore_event_signal_user_new();
269 if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
270 e->data = sigusr1_info[n];
272 _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
273 _ecore_signal_generic_free, NULL);
279 if (sigusr2_count > MAXSIGQ)
280 WRN("%i SIGUSR2 in queue. max queue size %i. losing "
281 "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
282 for (n = 0; n < sigusr2_count; n++)
284 Ecore_Event_Signal_User *e;
286 e = _ecore_event_signal_user_new();
291 if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
292 e->data = sigusr2_info[n];
294 _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
295 _ecore_signal_generic_free, NULL);
301 if (sighup_count > MAXSIGQ)
302 WRN("%i SIGHUP in queue. max queue size %i. losing "
303 "siginfo for extra signals.", sighup_count, MAXSIGQ);
304 for (n = 0; n < sighup_count; n++)
306 Ecore_Event_Signal_Hup *e;
308 e = _ecore_event_signal_hup_new();
311 if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
312 e->data = sighup_info[n];
314 _ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
315 _ecore_signal_generic_free, NULL);
321 if (sigquit_count > MAXSIGQ)
322 WRN("%i SIGQUIT in queue. max queue size %i. losing "
323 "siginfo for extra signals.", sigquit_count, MAXSIGQ);
324 for (n = 0; n < sigquit_count; n++)
326 Ecore_Event_Signal_Exit *e;
328 e = _ecore_event_signal_exit_new();
333 if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
334 e->data = sigquit_info[n];
336 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
337 _ecore_signal_generic_free, NULL);
343 if (sigint_count > MAXSIGQ)
344 WRN("%i SIGINT in queue. max queue size %i. losing "
345 "siginfo for extra signals.", sigint_count, MAXSIGQ);
346 for (n = 0; n < sigint_count; n++)
348 Ecore_Event_Signal_Exit *e;
350 e = _ecore_event_signal_exit_new();
355 if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
356 e->data = sigint_info[n];
358 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
359 _ecore_signal_generic_free, NULL);
365 if (sigterm_count > MAXSIGQ)
366 WRN("%i SIGTERM in queue. max queue size %i. losing "
367 "siginfo for extra signals.", sigterm_count, MAXSIGQ);
368 for (n = 0; n < sigterm_count; n++)
370 Ecore_Event_Signal_Exit *e;
372 e = _ecore_event_signal_exit_new();
377 if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
378 e->data = sigterm_info[n];
380 _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
381 _ecore_signal_generic_free, NULL);
388 if (sigpwr_count > MAXSIGQ)
389 WRN("%i SIGPWR in queue. max queue size %i. losing "
390 "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
391 for (n = 0; n < sigpwr_count; n++)
393 Ecore_Event_Signal_Power *e;
395 e = _ecore_event_signal_power_new();
398 if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
399 e->data = sigpwr_info[n];
401 _ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
402 _ecore_signal_generic_free, NULL);
410 sigprocmask(SIG_SETMASK, &oldset, NULL);
414 _ecore_signal_callback_set(int sig,
419 sa.sa_sigaction = func;
420 sa.sa_flags = SA_RESTART | SA_SIGINFO;
421 sigemptyset(&sa.sa_mask);
422 sigaction(sig, &sa, NULL);
426 _ecore_signal_callback_ignore(int sig __UNUSED__,
427 siginfo_t *si __UNUSED__,
428 void *foo __UNUSED__)
433 _ecore_signal_callback_sigchld(int sig __UNUSED__,
435 void *foo __UNUSED__)
437 volatile sig_atomic_t n;
442 sigchld_info[n] = *si;
444 sigchld_info[n].si_signo = 0;
452 _ecore_signal_callback_sigusr1(int sig __UNUSED__,
454 void *foo __UNUSED__)
456 volatile sig_atomic_t n;
461 sigusr1_info[n] = *si;
463 sigusr1_info[n].si_signo = 0;
470 _ecore_signal_callback_sigusr2(int sig __UNUSED__,
472 void *foo __UNUSED__)
474 volatile sig_atomic_t n;
479 sigusr2_info[n] = *si;
481 sigusr2_info[n].si_signo = 0;
488 _ecore_signal_callback_sighup(int sig __UNUSED__,
490 void *foo __UNUSED__)
492 volatile sig_atomic_t n;
497 sighup_info[n] = *si;
499 sighup_info[n].si_signo = 0;
506 _ecore_signal_callback_sigquit(int sig __UNUSED__,
508 void *foo __UNUSED__)
510 volatile sig_atomic_t n;
515 sigquit_info[n] = *si;
517 sigquit_info[n].si_signo = 0;
524 _ecore_signal_callback_sigint(int sig __UNUSED__,
526 void *foo __UNUSED__)
528 volatile sig_atomic_t n;
533 sigint_info[n] = *si;
535 sigint_info[n].si_signo = 0;
542 _ecore_signal_callback_sigterm(int sig __UNUSED__,
544 void *foo __UNUSED__)
546 volatile sig_atomic_t n;
551 sigterm_info[n] = *si;
553 sigterm_info[n].si_signo = 0;
561 _ecore_signal_callback_sigpwr(int sig __UNUSED__,
563 void *foo __UNUSED__)
565 volatile sig_atomic_t n;
570 sigpwr_info[n] = *si;
572 sigpwr_info[n].si_signo = 0;
581 _ecore_signal_exe_exit_delay(void *data)
583 Ecore_Exe_Event_Del *e;
588 _ecore_exe_doomsday_clock_set(e->exe, NULL);
589 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
590 _ecore_exe_event_del_free, NULL);
592 return ECORE_CALLBACK_CANCEL;