4c555c61b49ac0c9bf6ff4e58cc5c29b144c6af0
[framework/uifw/ecore.git] / src / lib / ecore / ecore_signal.c
1 #ifndef _WIN32
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <signal.h>
5 #include <unistd.h>
6 #include <assert.h>
7 #include "ecore_private.h"
8 #include "Ecore.h"
9
10 /* make mono happy - this is evil though... */
11 #undef SIGPWR
12 /* valgrind in some versions/setups uses SIGRT's... hmmm */
13 #undef SIGRTMIN
14
15 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
16
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);
26 #ifdef SIGPWR
27 static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
28 #endif
29
30 #ifdef SIGRTMIN
31 static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
32 #endif
33
34 static int _ecore_signal_exe_exit_delay(void *data);
35
36 //#define MAXSIGQ 256 // 32k
37 #define MAXSIGQ 64 // 8k
38
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;
47 #ifdef SIGPWR
48 static volatile sig_atomic_t sigpwr_count = 0;
49 #endif
50 #ifdef SIGRTMIN
51 static volatile sig_atomic_t *sigrt_count = NULL;
52 #endif
53
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];
61 #ifdef SIGPWR
62 static volatile siginfo_t sigpwr_info[MAXSIGQ];
63 #endif
64 #ifdef SIGRTMIN
65 static volatile siginfo_t *sigrt_info[MAXSIGQ];
66 #endif
67
68 void
69 _ecore_signal_shutdown(void)
70 {
71 #ifdef SIGRTMIN
72    int i, num = SIGRTMAX - SIGRTMIN;
73 #endif
74
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);
84 #ifdef SIGPWR
85    _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
86    sigpwr_count = 0;
87 #endif
88    sigchld_count = 0;
89    sigusr1_count = 0;
90    sigusr2_count = 0;
91    sighup_count = 0;
92    sigquit_count = 0;
93    sigint_count = 0;
94    sigterm_count = 0;
95    sig_count = 0;
96
97 #ifdef SIGRTMIN
98    for (i = 0; i < num; i++)
99      {
100         _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
101         sigrt_count[i] = 0;
102      }
103
104    if (sigrt_count)
105      {
106         free((sig_atomic_t *) sigrt_count);
107         sigrt_count = NULL;
108      }
109
110    for (i = 0; i < MAXSIGQ; i++)
111      {
112         if (sigrt_info[i])
113           {
114              free((siginfo_t *) sigrt_info[i]);
115              sigrt_info[i] = NULL;
116           }
117      }
118 #endif
119 }
120
121 void
122 _ecore_signal_init(void)
123 {
124 #ifdef SIGRTMIN
125    int i, num = SIGRTMAX - SIGRTMIN;
126 #endif
127
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);
137 #ifdef SIGPWR
138    _ecore_signal_callback_set(SIGPWR,  _ecore_signal_callback_sigpwr);
139 #endif
140
141 #ifdef SIGRTMIN
142    sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
143    assert(sigrt_count);
144
145    for (i = 0; i < MAXSIGQ; i++)
146      {
147         sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
148         assert(sigrt_info[i]);
149      }
150
151    for (i = 0; i < num; i++)
152       _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
153 #endif
154 }
155
156 int
157 _ecore_signal_count_get(void)
158 {
159    return sig_count;
160 }
161
162 void
163 _ecore_signal_call(void)
164 {
165 #ifdef SIGRTMIN
166    int i, num = SIGRTMAX - SIGRTMIN;
167 #endif
168    volatile sig_atomic_t n;
169    sigset_t oldset, newset;
170    
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);
182 #ifdef SIGPWR
183    sigaddset(&newset, SIGPWR);
184 #endif
185 #ifdef SIGRTMIN
186    for (i = 0; i < num; i++)
187      sigaddset(&newset, SIGRTMIN + i);
188 #endif   
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++)
194      {
195         pid_t pid;
196         int status;
197
198         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
199           {
200              Ecore_Exe_Event_Del *e;
201
202              /* FIXME: If this process is set respawn, respawn with a suitable backoff
203               * period for those that need too much respawning.
204               */
205              e = _ecore_exe_event_del_new();
206              if (e)
207                {
208                   if (WIFEXITED(status))
209                     {
210                        e->exit_code = WEXITSTATUS(status);
211                        e->exited = 1;
212                     }
213                   else if (WIFSIGNALED(status))
214                     {
215                        e->exit_signal = WTERMSIG(status);
216                        e->signalled = 1;
217                     }
218                   e->pid = pid;
219                   e->exe = _ecore_exe_find(pid);
220
221                   if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
222                     e->data = sigchld_info[n]; /* No need to clone this. */
223
224                   if ((e->exe) && (e->exe->flags & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
225                      {
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.
232                          *
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.
238                          *
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.
243                          *
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.
247                          */
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);
250                      }
251                   else
252                     {
253                        _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
254                                    _ecore_exe_event_del_free, NULL);
255                     }
256                }
257           }
258         sig_count--;
259      }
260    sigchld_count = 0;
261    
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++)
266      {
267         Ecore_Event_Signal_User *e;
268
269         e = _ecore_event_signal_user_new();
270         if (e)
271           {
272              e->number = 1;
273
274              if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
275                e->data = sigusr1_info[n];
276
277              ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
278           }
279         sig_count--;
280      }
281    sigusr1_count = 0;
282    
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++)
287      {
288         Ecore_Event_Signal_User *e;
289
290         e = _ecore_event_signal_user_new();
291         if (e)
292           {
293              e->number = 2;
294
295              if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
296                e->data = sigusr2_info[n];
297
298              ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
299           }
300         sig_count--;
301      }
302    sigusr2_count = 0;
303    
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++)
308      {
309         Ecore_Event_Signal_Hup *e;
310
311         e = _ecore_event_signal_hup_new();
312         if (e)
313           {
314              if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
315                e->data = sighup_info[n];
316
317              ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
318           }
319         sig_count--;
320      }
321    sighup_count = 0;
322    
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++)
327      {
328         Ecore_Event_Signal_Exit *e;
329
330         e = _ecore_event_signal_exit_new();
331         if (e)
332           {
333              e->quit = 1;
334
335              if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
336                e->data = sigquit_info[n];
337
338              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
339           }
340         sig_count--;
341      }
342    sigquit_count = 0;
343
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++)
348      {
349         Ecore_Event_Signal_Exit *e;
350
351         e = _ecore_event_signal_exit_new();
352         if (e)
353           {
354              e->interrupt = 1;
355
356              if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
357                e->data = sigint_info[n];
358
359              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
360           }
361         sig_count--;
362      }
363    sigint_count = 0;
364    
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++)
369      {
370         Ecore_Event_Signal_Exit *e;
371
372         e = _ecore_event_signal_exit_new();
373         if (e)
374           {
375              e->terminate = 1;
376
377              if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
378                e->data = sigterm_info[n];
379
380              ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
381           }
382         sig_count--;
383      }
384    sigterm_count = 0;
385    
386 #ifdef SIGPWR
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++)
391      {
392         Ecore_Event_Signal_Power *e;
393
394         e = _ecore_event_signal_power_new();
395         if (e)
396           {
397              if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
398                e->data = sigpwr_info[n];
399
400              ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
401           }
402         sig_count--;
403      }
404    sigpwr_count = 0;
405 #endif
406
407 #ifdef SIGRTMIN
408    for (i = 0; i < num; i++)
409      {
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++)
414           {
415              Ecore_Event_Signal_Realtime *e;
416
417              if ((e = _ecore_event_signal_realtime_new()))
418                {
419                   e->num = i;
420
421                   if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
422                     e->data = sigrt_info[n][i];
423
424                   ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
425                }
426              sig_count--;
427           }
428         sigrt_count[i] = 0;
429      }
430 #endif
431    sigprocmask(SIG_SETMASK, &oldset, NULL);
432 }
433
434 static void
435 _ecore_signal_callback_set(int sig, Signal_Handler func)
436 {
437    struct sigaction  sa;
438
439    sa.sa_sigaction = func;
440    sa.sa_flags = SA_RESTART | SA_SIGINFO;
441    sigemptyset(&sa.sa_mask);
442    sigaction(sig, &sa, NULL);
443 }
444
445 static void
446 _ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
447 {
448 }
449
450 static void
451 _ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
452 {
453    volatile sig_atomic_t n;
454    n = sigchld_count;
455    if (n < MAXSIGQ)
456      {
457         if (si)
458           sigchld_info[n] = *si;
459         else
460           sigchld_info[n].si_signo = 0;
461      }
462
463    sigchld_count++;
464    sig_count++;
465 }
466
467 static void
468 _ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
469 {
470    volatile sig_atomic_t n;
471    n = sigchld_count;
472    if (n < MAXSIGQ)
473      {
474         if (si)
475           sigusr1_info[n] = *si;
476         else
477           sigusr1_info[n].si_signo = 0;
478      }
479    sigusr1_count++;
480    sig_count++;
481 }
482
483 static void
484 _ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
485 {
486    volatile sig_atomic_t n;
487    n = sigchld_count;
488    if (n < MAXSIGQ)
489      {
490         if (si)
491           sigusr2_info[n] = *si;
492         else
493           sigusr2_info[n].si_signo = 0;
494      }
495    sigusr2_count++;
496    sig_count++;
497 }
498
499 static void
500 _ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
501 {
502    volatile sig_atomic_t n;
503    n = sigchld_count;
504    if (n < MAXSIGQ)
505      {
506         if (si)
507           sighup_info[n] = *si;
508         else
509           sighup_info[n].si_signo = 0;
510      }
511    sighup_count++;
512    sig_count++;
513 }
514
515 static void
516 _ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
517 {
518    volatile sig_atomic_t n;
519    n = sigchld_count;
520    if (n < MAXSIGQ)
521      {
522         if (si)
523           sigquit_info[n] = *si;
524         else
525           sigquit_info[n].si_signo = 0;
526      }
527    sigquit_count++;
528    sig_count++;
529 }
530
531 static void
532 _ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
533 {
534    volatile sig_atomic_t n;
535    n = sigchld_count;
536    if (n < MAXSIGQ)
537      {
538         if (si)
539           sigint_info[n] = *si;
540         else
541           sigint_info[n].si_signo = 0;
542      }
543    sigint_count++;
544    sig_count++;
545 }
546
547 static void
548 _ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
549 {
550    volatile sig_atomic_t n;
551    n = sigchld_count;
552    if (n < MAXSIGQ)
553      {
554         if (si)
555           sigterm_info[n] = *si;
556         else
557           sigterm_info[n].si_signo = 0;
558      }
559    sigterm_count++;
560    sig_count++;
561 }
562
563 #ifdef SIGPWR
564 static void
565 _ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
566 {
567    volatile sig_atomic_t n;
568    n = sigchld_count;
569    if (n < MAXSIGQ)
570      {
571         if (si)
572           sigpwr_info[n] = *si;
573         else
574           sigpwr_info[n].si_signo = 0;
575      }
576    sigpwr_count++;
577    sig_count++;
578 }
579 #endif
580
581 #ifdef SIGRTMIN
582 static void
583 _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
584 {
585    volatile sig_atomic_t n;
586    n = sigchld_count;
587    if (n < MAXSIGQ)
588      {
589         if (si)
590           sigrt_info[n][sig - SIGRTMIN] = *si;
591         else
592           sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
593      }
594    sigrt_count[sig - SIGRTMIN]++;
595    sig_count++;
596 }
597 #endif
598
599 static int
600 _ecore_signal_exe_exit_delay(void *data)
601 {
602    Ecore_Exe_Event_Del *e;
603
604    e = data;
605    if (e)
606      {
607         e->exe->doomsday_clock = NULL;
608         _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
609                          _ecore_exe_event_del_free, NULL);
610      }
611    return 0;
612 }
613 #endif