[ecore] merged svn latest code (svn54830)
[profile/ivi/ecore.git] / src / lib / ecore / ecore_signal.c
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 #undef SIGRTMIN
19
20 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
21
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);
31 #ifdef SIGPWR
32 static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
33 #endif
34
35 #ifdef SIGRTMIN
36 static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
37 #endif
38
39 static Eina_Bool _ecore_signal_exe_exit_delay(void *data);
40
41 //#define MAXSIGQ 256 // 32k
42 #define MAXSIGQ 64 // 8k
43
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;
52 #ifdef SIGPWR
53 static volatile sig_atomic_t sigpwr_count = 0;
54 #endif
55 #ifdef SIGRTMIN
56 static volatile sig_atomic_t *sigrt_count = NULL;
57 #endif
58
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];
66 #ifdef SIGPWR
67 static volatile siginfo_t sigpwr_info[MAXSIGQ];
68 #endif
69 #ifdef SIGRTMIN
70 static volatile siginfo_t *sigrt_info[MAXSIGQ];
71 #endif
72
73 void
74 _ecore_signal_shutdown(void)
75 {
76 #ifdef SIGRTMIN
77    int i, num = SIGRTMAX - SIGRTMIN;
78 #endif
79
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);
89 #ifdef SIGPWR
90    _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
91    sigpwr_count = 0;
92 #endif
93    sigchld_count = 0;
94    sigusr1_count = 0;
95    sigusr2_count = 0;
96    sighup_count = 0;
97    sigquit_count = 0;
98    sigint_count = 0;
99    sigterm_count = 0;
100    sig_count = 0;
101
102 #ifdef SIGRTMIN
103    for (i = 0; i < num; i++)
104      {
105         _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
106         sigrt_count[i] = 0;
107      }
108
109    if (sigrt_count)
110      {
111         free((sig_atomic_t *) sigrt_count);
112         sigrt_count = NULL;
113      }
114
115    for (i = 0; i < MAXSIGQ; i++)
116      {
117         if (sigrt_info[i])
118           {
119              free((siginfo_t *) sigrt_info[i]);
120              sigrt_info[i] = NULL;
121           }
122      }
123 #endif
124 }
125
126 void
127 _ecore_signal_init(void)
128 {
129 #ifdef SIGRTMIN
130    int i, num = SIGRTMAX - SIGRTMIN;
131 #endif
132
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);
142 #ifdef SIGPWR
143    _ecore_signal_callback_set(SIGPWR,  _ecore_signal_callback_sigpwr);
144 #endif
145
146 #ifdef SIGRTMIN
147    sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
148    assert(sigrt_count);
149
150    for (i = 0; i < MAXSIGQ; i++)
151      {
152         sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
153         assert(sigrt_info[i]);
154      }
155
156    for (i = 0; i < num; i++)
157       _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
158 #endif
159 }
160
161 int
162 _ecore_signal_count_get(void)
163 {
164    return sig_count;
165 }
166
167 void
168 _ecore_signal_call(void)
169 {
170 #ifdef SIGRTMIN
171    int i, num = SIGRTMAX - SIGRTMIN;
172 #endif
173    volatile sig_atomic_t n;
174    sigset_t oldset, newset;
175
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);
187 #ifdef SIGPWR
188    sigaddset(&newset, SIGPWR);
189 #endif
190 #ifdef SIGRTMIN
191    for (i = 0; i < num; i++)
192      sigaddset(&newset, SIGRTMIN + i);
193 #endif
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++)
199      {
200         pid_t pid;
201         int status;
202
203         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
204           {
205              Ecore_Exe_Event_Del *e;
206
207              /* FIXME: If this process is set respawn, respawn with a suitable backoff
208               * period for those that need too much respawning.
209               */
210              e = _ecore_exe_event_del_new();
211              if (e)
212                {
213                   if (WIFEXITED(status))
214                     {
215                        e->exit_code = WEXITSTATUS(status);
216                        e->exited = 1;
217                     }
218                   else if (WIFSIGNALED(status))
219                     {
220                        e->exit_signal = WTERMSIG(status);
221                        e->signalled = 1;
222                     }
223                   e->pid = pid;
224                   e->exe = _ecore_exe_find(pid);
225
226                   if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
227                     e->data = sigchld_info[n]; /* No need to clone this. */
228
229                   if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
230                      {
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.
237                          *
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.
243                          *
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.
248                          *
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.
252                          */
253                         Ecore_Timer *doomsday_clock;
254
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));
258                      }
259                   else
260                     {
261                        _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
262                                    _ecore_exe_event_del_free, NULL);
263                     }
264                }
265           }
266         sig_count--;
267      }
268    sigchld_count = 0;
269
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++)
274      {
275         Ecore_Event_Signal_User *e;
276
277         e = _ecore_event_signal_user_new();
278         if (e)
279           {
280              e->number = 1;
281
282              if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
283                e->data = sigusr1_info[n];
284
285              ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
286           }
287         sig_count--;
288      }
289    sigusr1_count = 0;
290
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++)
295      {
296         Ecore_Event_Signal_User *e;
297
298         e = _ecore_event_signal_user_new();
299         if (e)
300           {
301              e->number = 2;
302
303              if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
304                e->data = sigusr2_info[n];
305
306              ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
307           }
308         sig_count--;
309      }
310    sigusr2_count = 0;
311
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++)
316      {
317         Ecore_Event_Signal_Hup *e;
318
319         e = _ecore_event_signal_hup_new();
320         if (e)
321           {
322              if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
323                e->data = sighup_info[n];
324
325              ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
326           }
327         sig_count--;
328      }
329    sighup_count = 0;
330
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++)
335      {
336         Ecore_Event_Signal_Exit *e;
337
338         e = _ecore_event_signal_exit_new();
339         if (e)
340           {
341              e->quit = 1;
342
343              if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
344                e->data = sigquit_info[n];
345
346              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
347           }
348         sig_count--;
349      }
350    sigquit_count = 0;
351
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++)
356      {
357         Ecore_Event_Signal_Exit *e;
358
359         e = _ecore_event_signal_exit_new();
360         if (e)
361           {
362              e->interrupt = 1;
363
364              if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
365                e->data = sigint_info[n];
366
367              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
368           }
369         sig_count--;
370      }
371    sigint_count = 0;
372
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++)
377      {
378         Ecore_Event_Signal_Exit *e;
379
380         e = _ecore_event_signal_exit_new();
381         if (e)
382           {
383              e->terminate = 1;
384
385              if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
386                e->data = sigterm_info[n];
387
388              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
389           }
390         sig_count--;
391      }
392    sigterm_count = 0;
393
394 #ifdef SIGPWR
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++)
399      {
400         Ecore_Event_Signal_Power *e;
401
402         e = _ecore_event_signal_power_new();
403         if (e)
404           {
405              if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
406                e->data = sigpwr_info[n];
407
408              ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
409           }
410         sig_count--;
411      }
412    sigpwr_count = 0;
413 #endif
414
415 #ifdef SIGRTMIN
416    for (i = 0; i < num; i++)
417      {
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++)
422           {
423              Ecore_Event_Signal_Realtime *e;
424
425              if ((e = _ecore_event_signal_realtime_new()))
426                {
427                   e->num = i;
428
429                   if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
430                     e->data = sigrt_info[n][i];
431
432                   ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
433                }
434              sig_count--;
435           }
436         sigrt_count[i] = 0;
437      }
438 #endif
439    sigprocmask(SIG_SETMASK, &oldset, NULL);
440 }
441
442 static void
443 _ecore_signal_callback_set(int sig, Signal_Handler func)
444 {
445    struct sigaction  sa;
446
447    sa.sa_sigaction = func;
448    sa.sa_flags = SA_RESTART | SA_SIGINFO;
449    sigemptyset(&sa.sa_mask);
450    sigaction(sig, &sa, NULL);
451 }
452
453 static void
454 _ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
455 {
456 }
457
458 static void
459 _ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
460 {
461    volatile sig_atomic_t n;
462    n = sigchld_count;
463    if (n < MAXSIGQ)
464      {
465         if (si)
466           sigchld_info[n] = *si;
467         else
468           sigchld_info[n].si_signo = 0;
469      }
470
471    sigchld_count++;
472    sig_count++;
473 }
474
475 static void
476 _ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
477 {
478    volatile sig_atomic_t n;
479    n = sigusr1_count;
480    if (n < MAXSIGQ)
481      {
482         if (si)
483           sigusr1_info[n] = *si;
484         else
485           sigusr1_info[n].si_signo = 0;
486      }
487    sigusr1_count++;
488    sig_count++;
489 }
490
491 static void
492 _ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
493 {
494    volatile sig_atomic_t n;
495    n = sigusr2_count;
496    if (n < MAXSIGQ)
497      {
498         if (si)
499           sigusr2_info[n] = *si;
500         else
501           sigusr2_info[n].si_signo = 0;
502      }
503    sigusr2_count++;
504    sig_count++;
505 }
506
507 static void
508 _ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
509 {
510    volatile sig_atomic_t n;
511    n = sighup_count;
512    if (n < MAXSIGQ)
513      {
514         if (si)
515           sighup_info[n] = *si;
516         else
517           sighup_info[n].si_signo = 0;
518      }
519    sighup_count++;
520    sig_count++;
521 }
522
523 static void
524 _ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
525 {
526    volatile sig_atomic_t n;
527    n = sigquit_count;
528    if (n < MAXSIGQ)
529      {
530         if (si)
531           sigquit_info[n] = *si;
532         else
533           sigquit_info[n].si_signo = 0;
534      }
535    sigquit_count++;
536    sig_count++;
537 }
538
539 static void
540 _ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
541 {
542    volatile sig_atomic_t n;
543    n = sigint_count;
544    if (n < MAXSIGQ)
545      {
546         if (si)
547           sigint_info[n] = *si;
548         else
549           sigint_info[n].si_signo = 0;
550      }
551    sigint_count++;
552    sig_count++;
553 }
554
555 static void
556 _ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
557 {
558    volatile sig_atomic_t n;
559    n = sigterm_count;
560    if (n < MAXSIGQ)
561      {
562         if (si)
563           sigterm_info[n] = *si;
564         else
565           sigterm_info[n].si_signo = 0;
566      }
567    sigterm_count++;
568    sig_count++;
569 }
570
571 #ifdef SIGPWR
572 static void
573 _ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
574 {
575    volatile sig_atomic_t n;
576    n = sigpwr_count;
577    if (n < MAXSIGQ)
578      {
579         if (si)
580           sigpwr_info[n] = *si;
581         else
582           sigpwr_info[n].si_signo = 0;
583      }
584    sigpwr_count++;
585    sig_count++;
586 }
587 #endif
588
589 #ifdef SIGRTMIN
590 static void
591 _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
592 {
593    volatile sig_atomic_t n;
594    n = sigrt_count[sig - SIGRTMIN];
595    if (n < MAXSIGQ)
596      {
597         if (si)
598           sigrt_info[n][sig - SIGRTMIN] = *si;
599         else
600           sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
601      }
602    sigrt_count[sig - SIGRTMIN]++;
603    sig_count++;
604 }
605 #endif
606
607 static Eina_Bool
608 _ecore_signal_exe_exit_delay(void *data)
609 {
610    Ecore_Exe_Event_Del *e;
611
612    e = data;
613    if (e)
614      {
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);
618      }
619    return ECORE_CALLBACK_CANCEL;
620 }