aboutsummaryrefslogtreecommitdiff
path: root/src/util/child_management.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
commit9ef4abad615bea12d13be542b8ae5fbeb2dfee32 (patch)
tree8875a687e004d331c9ea6a1d511a328c72b88113 /src/util/child_management.c
parente95236b3ed78cd597c15f34b89385295702b627f (diff)
downloadgnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.tar.gz
gnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.zip
NEWS: Refactoring components under src/ into lib/, plugin/, cli/ and service/
This also includes a necessary API refactoring of crypto from IDENTITY to UTIL.
Diffstat (limited to 'src/util/child_management.c')
-rw-r--r--src/util/child_management.c240
1 files changed, 0 insertions, 240 deletions
diff --git a/src/util/child_management.c b/src/util/child_management.c
deleted file mode 100644
index e78ebac9f..000000000
--- a/src/util/child_management.c
+++ /dev/null
@@ -1,240 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021-2023 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/child_management.c
23 * @brief Handling of child processes in GNUnet.
24 * @author Christian Grothoff (ANASTASIS)
25 * @author Dominik Meister (ANASTASIS)
26 * @author t3sserakt
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31
32/**
33 * Generic logging shortcut
34 */
35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
36
37
38/**
39 * Struct which defines a Child Wait handle
40 */
41struct GNUNET_ChildWaitHandle
42{
43 /**
44 * Linked list to the next child
45 */
46 struct GNUNET_ChildWaitHandle *next;
47 /**
48 * Linked list to the previous child
49 */
50 struct GNUNET_ChildWaitHandle *prev;
51 /**
52 * Child process which is managed
53 */
54 struct GNUNET_OS_Process *proc;
55 /**
56 * Callback which is called upon completion/death of the child task
57 */
58 GNUNET_ChildCompletedCallback cb;
59 /**
60 * Closure for the handle
61 */
62 void *cb_cls;
63};
64
65
66/**
67 * Pipe used to communicate shutdown via signal.
68 */
69static struct GNUNET_DISK_PipeHandle *sigpipe;
70
71static struct GNUNET_SIGNAL_Context *shc_chld;
72
73static struct GNUNET_SCHEDULER_Task *sig_task;
74
75static struct GNUNET_ChildWaitHandle *cwh_head;
76
77static struct GNUNET_ChildWaitHandle *cwh_tail;
78
79/**
80 * Task triggered whenever we receive a SIGCHLD (child
81 * process died) or when user presses CTRL-C.
82 *
83 * @param cls closure, NULL
84 */
85static void
86maint_child_death (void *cls)
87{
88 char buf[16];
89 const struct GNUNET_DISK_FileHandle *pr;
90 struct GNUNET_ChildWaitHandle *nxt;
91
92 (void) cls;
93 sig_task = NULL;
94 /* drain pipe */
95 pr = GNUNET_DISK_pipe_handle (sigpipe,
96 GNUNET_DISK_PIPE_END_READ);
97 GNUNET_assert (! GNUNET_DISK_handle_invalid (pr));
98 (void) GNUNET_DISK_file_read (pr,
99 buf,
100 sizeof(buf));
101
102 /* find applicable processes that exited */
103 for (struct GNUNET_ChildWaitHandle *cwh = cwh_head;
104 NULL != cwh;
105 cwh = nxt)
106 {
107 enum GNUNET_OS_ProcessStatusType type;
108 long unsigned int exit_code = 0;
109
110 nxt = cwh->next;
111 if (GNUNET_OK ==
112 GNUNET_OS_process_status (cwh->proc,
113 &type,
114 &exit_code))
115 {
116 GNUNET_CONTAINER_DLL_remove (cwh_head,
117 cwh_tail,
118 cwh);
119 cwh->cb (cwh->cb_cls,
120 type,
121 exit_code);
122 GNUNET_free (cwh);
123 }
124 }
125 if (NULL == cwh_head)
126 return;
127 /* wait for more */
128 sig_task = GNUNET_SCHEDULER_add_read_file (
129 GNUNET_TIME_UNIT_FOREVER_REL,
130 GNUNET_DISK_pipe_handle (sigpipe,
131 GNUNET_DISK_PIPE_END_READ),
132 &maint_child_death,
133 NULL);
134}
135
136
137/**
138 * Signal handler called for SIGCHLD. Triggers the
139 * respective handler by writing to the trigger pipe.
140 */
141static void
142sighandler_child_death (void)
143{
144 static char c;
145 int old_errno = errno; /* back-up errno */
146
147 GNUNET_break (
148 1 ==
149 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
150 GNUNET_DISK_PIPE_END_WRITE),
151 &c,
152 sizeof(c)));
153 errno = old_errno; /* restore errno */
154}
155
156
157/**
158 * Initializing the signal pipe for child handling.
159 */
160static void
161child_management_start (void)
162{
163 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
164 "Trying to start child management.\n");
165 if (NULL != sigpipe)
166 return; /* already initialized */
167 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
168 GNUNET_assert (sigpipe != NULL);
169 shc_chld =
170 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
171 &sighandler_child_death);
172 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
173 "Child management started.\n");
174}
175
176
177/**
178 * Clean up.
179 */
180static void
181child_management_done (void)
182{
183 if (NULL != sig_task)
184 {
185 GNUNET_SCHEDULER_cancel (sig_task);
186 sig_task = NULL;
187 }
188 GNUNET_SIGNAL_handler_uninstall (shc_chld);
189 shc_chld = NULL;
190 GNUNET_DISK_pipe_close (sigpipe);
191 sigpipe = NULL;
192 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
193 "Child management stopped.\n");
194}
195
196
197struct GNUNET_ChildWaitHandle *
198GNUNET_wait_child (struct GNUNET_OS_Process *proc,
199 GNUNET_ChildCompletedCallback cb,
200 void *cb_cls)
201{
202 struct GNUNET_ChildWaitHandle *cwh;
203 bool may_race = (NULL == sigpipe);
204
205 child_management_start ();
206 cwh = GNUNET_new (struct GNUNET_ChildWaitHandle);
207 cwh->proc = proc;
208 cwh->cb = cb;
209 cwh->cb_cls = cb_cls;
210 GNUNET_CONTAINER_DLL_insert (cwh_head,
211 cwh_tail,
212 cwh);
213 if (NULL == sig_task)
214 {
215 sig_task = GNUNET_SCHEDULER_add_read_file (
216 GNUNET_TIME_UNIT_FOREVER_REL,
217 GNUNET_DISK_pipe_handle (sigpipe,
218 GNUNET_DISK_PIPE_END_READ),
219 &maint_child_death,
220 NULL);
221 }
222 /* Handle race-condition case where the child terminated just before we
223 installed the signal handler and thus we missed the signal. */
224 if (may_race)
225 sighandler_child_death ();
226 return cwh;
227}
228
229
230void
231GNUNET_wait_child_cancel (struct GNUNET_ChildWaitHandle *cwh)
232{
233 GNUNET_CONTAINER_DLL_remove (cwh_head,
234 cwh_tail,
235 cwh);
236 GNUNET_free (cwh);
237 if (NULL != cwh_head)
238 return;
239 child_management_done ();
240}