7 #include "ecore_private.h"
10 /* make mono happy - this is evil though... */
12 /* valgrind in some versions/setups uses SIGRT's... hmmm */
15 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
17 static void _ecore_signal_callback_set(int sig, Signal_Handler func);
18 static void _ecore_signal_callback_ignore(int sig, siginfo_t *si, void *foo);
19 static void _ecore_signal_callback_sigchld(int sig, siginfo_t *si, void *foo);
20 static void _ecore_signal_callback_sigusr1(int sig, siginfo_t *si, void *foo);
21 static void _ecore_signal_callback_sigusr2(int sig, siginfo_t *si, void *foo);
22 static void _ecore_signal_callback_sighup(int sig, siginfo_t *si, void *foo);
23 static void _ecore_signal_callback_sigquit(int sig, siginfo_t *si, void *foo);
24 static void _ecore_signal_callback_sigint(int sig, siginfo_t *si, void *foo);
25 static void _ecore_signal_callback_sigterm(int sig, siginfo_t *si, void *foo);
27 static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
31 static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
34 static int _ecore_signal_exe_exit_delay(void *data);
36 //#define MAXSIGQ 256 // 32k
37 #define MAXSIGQ 64 // 8k
39 static volatile sig_atomic_t sig_count = 0;
40 static volatile sig_atomic_t sigchld_count = 0;
41 static volatile sig_atomic_t sigusr1_count = 0;
42 static volatile sig_atomic_t sigusr2_count = 0;
43 static volatile sig_atomic_t sighup_count = 0;
44 static volatile sig_atomic_t sigquit_count = 0;
45 static volatile sig_atomic_t sigint_count = 0;
46 static volatile sig_atomic_t sigterm_count = 0;
48 static volatile sig_atomic_t sigpwr_count = 0;
51 static volatile sig_atomic_t *sigrt_count = NULL;
54 static volatile siginfo_t sigchld_info[MAXSIGQ];
55 static volatile siginfo_t sigusr1_info[MAXSIGQ];
56 static volatile siginfo_t sigusr2_info[MAXSIGQ];
57 static volatile siginfo_t sighup_info[MAXSIGQ];
58 static volatile siginfo_t sigquit_info[MAXSIGQ];
59 static volatile siginfo_t sigint_info[MAXSIGQ];
60 static volatile siginfo_t sigterm_info[MAXSIGQ];
62 static volatile siginfo_t sigpwr_info[MAXSIGQ];
65 static volatile siginfo_t *sigrt_info[MAXSIGQ];
69 _ecore_signal_shutdown(void)
72 int i, num = SIGRTMAX - SIGRTMIN;
75 _ecore_signal_callback_set(SIGPIPE, (Signal_Handler) SIG_DFL);
76 _ecore_signal_callback_set(SIGALRM, (Signal_Handler) SIG_DFL);
77 _ecore_signal_callback_set(SIGCHLD, (Signal_Handler) SIG_DFL);
78 _ecore_signal_callback_set(SIGUSR1, (Signal_Handler) SIG_DFL);
79 _ecore_signal_callback_set(SIGUSR2, (Signal_Handler) SIG_DFL);
80 _ecore_signal_callback_set(SIGHUP, (Signal_Handler) SIG_DFL);
81 _ecore_signal_callback_set(SIGQUIT, (Signal_Handler) SIG_DFL);
82 _ecore_signal_callback_set(SIGINT, (Signal_Handler) SIG_DFL);
83 _ecore_signal_callback_set(SIGTERM, (Signal_Handler) SIG_DFL);
85 _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
98 for (i = 0; i < num; i++)
100 _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
106 free((sig_atomic_t *) sigrt_count);
110 for (i = 0; i < MAXSIGQ; i++)
114 free((siginfo_t *) sigrt_info[i]);
115 sigrt_info[i] = NULL;
122 _ecore_signal_init(void)
125 int i, num = SIGRTMAX - SIGRTMIN;
128 _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
129 _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
130 _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
131 _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
132 _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
133 _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
134 _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
135 _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
136 _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
138 _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
142 sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
145 for (i = 0; i < MAXSIGQ; i++)
147 sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
148 assert(sigrt_info[i]);
151 for (i = 0; i < num; i++)
152 _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
157 _ecore_signal_count_get(void)
163 _ecore_signal_call(void)
166 int i, num = SIGRTMAX - SIGRTMIN;
168 volatile sig_atomic_t n;
169 sigset_t oldset, newset;
171 if (sig_count == 0) return;
172 sigemptyset(&newset);
173 sigaddset(&newset, SIGPIPE);
174 sigaddset(&newset, SIGALRM);
175 sigaddset(&newset, SIGCHLD);
176 sigaddset(&newset, SIGUSR1);
177 sigaddset(&newset, SIGUSR2);
178 sigaddset(&newset, SIGHUP);
179 sigaddset(&newset, SIGQUIT);
180 sigaddset(&newset, SIGINT);
181 sigaddset(&newset, SIGTERM);
183 sigaddset(&newset, SIGPWR);
186 for (i = 0; i < num; i++)
187 sigaddset(&newset, SIGRTMIN + i);
189 sigprocmask(SIG_BLOCK, &newset, &oldset);
190 if (sigchld_count > MAXSIGQ)
191 printf("ECORE WARNING. %i SIGCHLD in queue. max queue size %i. losing "
192 "siginfo for extra signals.\n", sigchld_count, MAXSIGQ);
193 for (n = 0; n < sigchld_count; n++)
198 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
200 Ecore_Exe_Event_Del *e;
202 /* FIXME: If this process is set respawn, respawn with a suitable backoff
203 * period for those that need too much respawning.
205 e = _ecore_exe_event_del_new();
208 if (WIFEXITED(status))
210 e->exit_code = WEXITSTATUS(status);
213 else if (WIFSIGNALED(status))
215 e->exit_signal = WTERMSIG(status);
219 e->exe = _ecore_exe_find(pid);
221 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
222 e->data = sigchld_info[n]; /* No need to clone this. */
224 if ((e->exe) && (e->exe->flags & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
226 /* We want to report the Last Words of the exe, so delay this event.
227 * This is twice as relevant for stderr.
228 * There are three possibilities here -
229 * 1 There are no Last Words.
230 * 2 There are Last Words, they are not ready to be read.
231 * 3 There are Last Words, they are ready to be read.
233 * For 1 we don't want to delay, for 3 we want to delay.
234 * 2 is the problem. If we check for data now and there
235 * is none, then there is no way to differentiate 1 and 2.
236 * If we don't delay, we may loose data, but if we do delay,
237 * there may not be data and the exit event never gets sent.
239 * Any way you look at it, there has to be some time passed
240 * before the exit event gets sent. So the strategy here is
241 * to setup a timer event that will send the exit event after
242 * an arbitrary, but brief, time.
244 * This is probably paranoid, for the less paraniod, we could
245 * check to see for Last Words, and only delay if there are any.
246 * This has it's own set of problems.
248 IF_FN_DEL(ecore_timer_del, e->exe->doomsday_clock);
249 e->exe->doomsday_clock = ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e);
253 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
254 _ecore_exe_event_del_free, NULL);
262 if (sigusr1_count > MAXSIGQ)
263 printf("ECORE WARNING. %i SIGUSR1 in queue. max queue size %i. losing "
264 "siginfo for extra signals.\n", sigusr1_count, MAXSIGQ);
265 for (n = 0; n < sigusr1_count; n++)
267 Ecore_Event_Signal_User *e;
269 e = _ecore_event_signal_user_new();
274 if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
275 e->data = sigusr1_info[n];
277 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
283 if (sigusr2_count > MAXSIGQ)
284 printf("ECORE WARNING. %i SIGUSR2 in queue. max queue size %i. losing "
285 "siginfo for extra signals.\n", sigusr2_count, MAXSIGQ);
286 for (n = 0; n < sigusr2_count; n++)
288 Ecore_Event_Signal_User *e;
290 e = _ecore_event_signal_user_new();
295 if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
296 e->data = sigusr2_info[n];
298 ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
304 if (sighup_count > MAXSIGQ)
305 printf("ECORE WARNING. %i SIGHUP in queue. max queue size %i. losing "
306 "siginfo for extra signals.\n", sighup_count, MAXSIGQ);
307 for (n = 0; n < sighup_count; n++)
309 Ecore_Event_Signal_Hup *e;
311 e = _ecore_event_signal_hup_new();
314 if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
315 e->data = sighup_info[n];
317 ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
323 if (sigquit_count > MAXSIGQ)
324 printf("ECORE WARNING. %i SIGQUIT in queue. max queue size %i. losing "
325 "siginfo for extra signals.\n", sigquit_count, MAXSIGQ);
326 for (n = 0; n < sigquit_count; n++)
328 Ecore_Event_Signal_Exit *e;
330 e = _ecore_event_signal_exit_new();
335 if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
336 e->data = sigquit_info[n];
338 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
344 if (sigint_count > MAXSIGQ)
345 printf("ECORE WARNING. %i SIGINT in queue. max queue size %i. losing "
346 "siginfo for extra signals.\n", sigint_count, MAXSIGQ);
347 for (n = 0; n < sigint_count; n++)
349 Ecore_Event_Signal_Exit *e;
351 e = _ecore_event_signal_exit_new();
356 if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
357 e->data = sigint_info[n];
359 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
365 if (sigterm_count > MAXSIGQ)
366 printf("ECORE WARNING. %i SIGTERM in queue. max queue size %i. losing "
367 "siginfo for extra signals.\n", 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, NULL, NULL);
387 if (sigpwr_count > MAXSIGQ)
388 printf("ECORE WARNING. %i SIGPWR in queue. max queue size %i. losing "
389 "siginfo for extra signals.\n", sigpwr_count, MAXSIGQ);
390 for (n = 0; n < sigpwr_count; n++)
392 Ecore_Event_Signal_Power *e;
394 e = _ecore_event_signal_power_new();
397 if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
398 e->data = sigpwr_info[n];
400 ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
408 for (i = 0; i < num; i++)
410 if (sigrt_count[i] > MAXSIGQ)
411 printf("ECORE WARNING. %i SIGRT%i in queue. max queue size %i. losing "
412 "siginfo for extra signals.\n", i + 1, sigrt_count[i], MAXSIGQ);
413 for (n = 0; n < sigrt_count[i]; n++)
415 Ecore_Event_Signal_Realtime *e;
417 if ((e = _ecore_event_signal_realtime_new()))
421 if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
422 e->data = sigrt_info[n][i];
424 ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
431 sigprocmask(SIG_SETMASK, &oldset, NULL);
435 _ecore_signal_callback_set(int sig, Signal_Handler func)
439 sa.sa_sigaction = func;
440 sa.sa_flags = SA_RESTART | SA_SIGINFO;
441 sigemptyset(&sa.sa_mask);
442 sigaction(sig, &sa, NULL);
446 _ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
451 _ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
453 volatile sig_atomic_t n;
458 sigchld_info[n] = *si;
460 sigchld_info[n].si_signo = 0;
468 _ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
470 volatile sig_atomic_t n;
475 sigusr1_info[n] = *si;
477 sigusr1_info[n].si_signo = 0;
484 _ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
486 volatile sig_atomic_t n;
491 sigusr2_info[n] = *si;
493 sigusr2_info[n].si_signo = 0;
500 _ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
502 volatile sig_atomic_t n;
507 sighup_info[n] = *si;
509 sighup_info[n].si_signo = 0;
516 _ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
518 volatile sig_atomic_t n;
523 sigquit_info[n] = *si;
525 sigquit_info[n].si_signo = 0;
532 _ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
534 volatile sig_atomic_t n;
539 sigint_info[n] = *si;
541 sigint_info[n].si_signo = 0;
548 _ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
550 volatile sig_atomic_t n;
555 sigterm_info[n] = *si;
557 sigterm_info[n].si_signo = 0;
565 _ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
567 volatile sig_atomic_t n;
572 sigpwr_info[n] = *si;
574 sigpwr_info[n].si_signo = 0;
583 _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
585 volatile sig_atomic_t n;
590 sigrt_info[n][sig - SIGRTMIN] = *si;
592 sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
594 sigrt_count[sig - SIGRTMIN]++;
600 _ecore_signal_exe_exit_delay(void *data)
602 Ecore_Exe_Event_Del *e;
607 e->exe->doomsday_clock = NULL;
608 _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
609 _ecore_exe_event_del_free, NULL);