1 /*
2  * sigchld.c - event for SIGCHLD
3  * Copyright (c) 2013 The Chromium Authors. All rights reserved.
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "config.h"
9 
10 #include <errno.h>
11 #include <event2/event.h>
12 #include <sys/wait.h>
13 #include <sys/types.h>
14 
15 #include "src/conf.h"
16 #include "src/util.h"
17 #include "src/tlsdate.h"
18 
19 /* Returns 1 if a death was handled, otherwise 0. */
20 int
handle_child_death(struct state * state)21 handle_child_death (struct state *state)
22 {
23   siginfo_t info;
24   int ret;
25   info.si_pid = 0;
26   ret = waitid (P_ALL, -1, &info, WEXITED|WNOHANG);
27   if (ret == -1)
28     {
29       if (errno == ECHILD)
30         return 0;
31       perror ("[event:%s] waitid() failed after SIGCHLD", __func__);
32       return 0;
33     }
34   if (info.si_pid == 0)
35     {
36       return 0;
37     }
38   if (info.si_pid == state->setter_pid)
39     {
40       report_setter_error (&info);
41       event_base_loopbreak (state->base);
42       return 1;
43     }
44   if (info.si_pid != state->tlsdate_pid)
45     {
46       error ("[event:%s] SIGCHLD for an unknown process -- "
47              "pid:%d uid:%d status:%d code:%d", __func__,
48              info.si_pid, info.si_uid, info.si_status, info.si_code);
49       return 1;
50     }
51   verb ("[event:%s] tlsdate reaped => "
52         "pid:%d uid:%d status:%d code:%d", __func__,
53         info.si_pid, info.si_uid, info.si_status, info.si_code);
54 
55   /* If it was still active, remove it. */
56   event_del (state->events[E_TLSDATE_TIMEOUT]);
57   state->running = 0;
58   state->tlsdate_pid = 0;
59   /* Clean exit - don't rerun! */
60   if (info.si_status == 0)
61     return 1;
62   verb_debug ("[event:%s] scheduling a retry", __func__);
63   /* Rerun a failed tlsdate */
64   if (state->backoff < MAX_SANE_BACKOFF)
65     state->backoff *= 2;
66   /* If there is no resolver, call tlsdate directly. */
67   if (!state->events[E_RESOLVER])
68     {
69       trigger_event (state, E_TLSDATE, state->backoff);
70       return 1;
71     }
72   /* Run tlsdate even if the resolver doesn't come back. */
73   trigger_event (state, E_TLSDATE, RESOLVER_TIMEOUT + state->backoff);
74   /* Schedule the resolver.  This is always done after tlsdate in case there
75    * is no resolver.
76    */
77   trigger_event (state, E_RESOLVER, state->backoff);
78   return 1;
79 }
80 
81 /* Returns 1 if a death was handled, otherwise 0. */
82 int
handle_child_stop(struct state * state)83 handle_child_stop (struct state *state)
84 {
85   /* Handle unexpected external interactions */
86   siginfo_t info;
87   int ret;
88   info.si_pid = 0;
89   ret = waitid (P_ALL, -1, &info, WSTOPPED|WCONTINUED|WNOHANG);
90   if (ret == -1)
91     {
92       if (errno == ECHILD)
93         return 0;
94       perror ("[event:%s] waitid() failed after SIGCHLD", __func__);
95       return 0;
96     }
97   if (info.si_pid == 0)
98     return 0;
99   info ("[event:%s] a child has been STOPPED or CONTINUED. Killing it.",
100          __func__);
101   /* Kill it then catch the next SIGCHLD. */
102   if (kill (info.si_pid, SIGKILL))
103     {
104       if (errno == EPERM)
105         fatal ("[event:%s] cannot terminate STOPPED privileged child",
106                __func__);
107       if (errno == ESRCH)
108         info ("[event:%s] child gone before we could kill it",
109               __func__);
110     }
111   return 1;
112 }
113 
114 void
action_sigchld(evutil_socket_t fd,short what,void * arg)115 action_sigchld (evutil_socket_t fd, short what, void *arg)
116 {
117   struct state *state = arg;
118   verb_debug ("[event:%s] a child process has SIGCHLD'd!", __func__);
119   /* Process SIGCHLDs in two steps: death and stopped until all
120    * pending children are sorted.
121    */
122   if (!handle_child_death (state) && !handle_child_stop (state))
123     verb ("[event:%s] SIGCHLD fired but no children ready!", __func__);
124   while (handle_child_death (state) || handle_child_stop (state));
125 }
126 
127 int
setup_sigchld_event(struct state * state,int persist)128 setup_sigchld_event (struct state *state, int persist)
129 {
130   state->events[E_SIGCHLD] = event_new (state->base, SIGCHLD,
131                                         EV_SIGNAL| (persist ? EV_PERSIST : 0),
132                                         action_sigchld, state);
133   if (!state->events[E_SIGCHLD])
134     return 1;
135   /* Make sure this is lower than SAVE so we get any error
136    * messages back from the time setter.
137    */
138   event_priority_set (state->events[E_SIGCHLD], PRI_NET);
139   event_add (state->events[E_SIGCHLD], NULL);
140   return 0;
141 }
142