aboutsummaryrefslogtreecommitdiff
path: root/src/util/child_management.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/child_management.c')
-rw-r--r--src/util/child_management.c247
1 files changed, 0 insertions, 247 deletions
diff --git a/src/util/child_management.c b/src/util/child_management.c
deleted file mode 100644
index 832e05ece..000000000
--- a/src/util/child_management.c
+++ /dev/null
@@ -1,247 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_child_management_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 * Initializing the signal pipe for child handling.
158 */
159static void
160child_management_start (void)
161{
162 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
163 "Trying to start child management.\n");
164 if (NULL != sigpipe)
165 return; /* already initialized */
166 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
167 GNUNET_assert (sigpipe != NULL);
168 shc_chld =
169 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
170 &sighandler_child_death);
171 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
172 "Child management started.\n");
173}
174
175
176/**
177 * Clean up.
178 */
179static void
180child_management_done (void)
181{
182 if (NULL != sig_task)
183 {
184 GNUNET_SCHEDULER_cancel (sig_task);
185 sig_task = NULL;
186 }
187 GNUNET_SIGNAL_handler_uninstall (shc_chld);
188 shc_chld = NULL;
189 GNUNET_DISK_pipe_close (sigpipe);
190 sigpipe = NULL;
191 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
192 "Child management stopped.\n");
193}
194
195
196/**
197 * Adding a child process to be monitored by the child management.
198 *
199 * @param proc The child process to be monitored.
200 * @param cp The callback to be called, when the child process completed.
201 * @param cb_cls The closure for the callback.
202 * @return An handle for the the child being monitored.
203 */
204struct GNUNET_ChildWaitHandle *
205GNUNET_wait_child (struct GNUNET_OS_Process *proc,
206 GNUNET_ChildCompletedCallback cb,
207 void *cb_cls)
208{
209 struct GNUNET_ChildWaitHandle *cwh;
210
211 child_management_start ();
212 cwh = GNUNET_new (struct GNUNET_ChildWaitHandle);
213 cwh->proc = proc;
214 cwh->cb = cb;
215 cwh->cb_cls = cb_cls;
216 GNUNET_CONTAINER_DLL_insert (cwh_head,
217 cwh_tail,
218 cwh);
219 if (NULL == sig_task)
220 {
221 sig_task = GNUNET_SCHEDULER_add_read_file (
222 GNUNET_TIME_UNIT_FOREVER_REL,
223 GNUNET_DISK_pipe_handle (sigpipe,
224 GNUNET_DISK_PIPE_END_READ),
225 &maint_child_death,
226 NULL);
227 }
228 return cwh;
229}
230
231
232/**
233 * Removing child handle.
234 *
235 * @param cwh The handle to be removed.
236 */
237void
238GNUNET_wait_child_cancel (struct GNUNET_ChildWaitHandle *cwh)
239{
240 GNUNET_CONTAINER_DLL_remove (cwh_head,
241 cwh_tail,
242 cwh);
243 GNUNET_free (cwh);
244 if (NULL != cwh_head)
245 return;
246 child_management_done ();
247}