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