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.c232
1 files changed, 0 insertions, 232 deletions
diff --git a/src/util/child_management.c b/src/util/child_management.c
deleted file mode 100644
index 4ef42dba2..000000000
--- a/src/util/child_management.c
+++ /dev/null
@@ -1,232 +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 testing/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
157static void
158child_management_start (void)
159{
160 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
161 "Trying to start child management.\n");
162 if (NULL != sigpipe)
163 return; /* already initialized */
164 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
165 GNUNET_assert (sigpipe != NULL);
166 shc_chld =
167 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
168 &sighandler_child_death);
169 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
170 "Child management started.\n");
171}
172
173
174/**
175 * Clean up.
176 */
177static void
178child_management_done (void)
179{
180 if (NULL != sig_task)
181 {
182 GNUNET_SCHEDULER_cancel (sig_task);
183 sig_task = NULL;
184 }
185 GNUNET_SIGNAL_handler_uninstall (shc_chld);
186 shc_chld = NULL;
187 GNUNET_DISK_pipe_close (sigpipe);
188 sigpipe = NULL;
189 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
190 "Child management stopped.\n");
191}
192
193
194struct GNUNET_ChildWaitHandle *
195GNUNET_wait_child (struct GNUNET_OS_Process *proc,
196 GNUNET_ChildCompletedCallback cb,
197 void *cb_cls)
198{
199 struct GNUNET_ChildWaitHandle *cwh;
200
201 child_management_start ();
202 cwh = GNUNET_new (struct GNUNET_ChildWaitHandle);
203 cwh->proc = proc;
204 cwh->cb = cb;
205 cwh->cb_cls = cb_cls;
206 GNUNET_CONTAINER_DLL_insert (cwh_head,
207 cwh_tail,
208 cwh);
209 if (NULL == sig_task)
210 {
211 sig_task = GNUNET_SCHEDULER_add_read_file (
212 GNUNET_TIME_UNIT_FOREVER_REL,
213 GNUNET_DISK_pipe_handle (sigpipe,
214 GNUNET_DISK_PIPE_END_READ),
215 &maint_child_death,
216 NULL);
217 }
218 return cwh;
219}
220
221
222void
223GNUNET_wait_child_cancel (struct GNUNET_ChildWaitHandle *cwh)
224{
225 GNUNET_CONTAINER_DLL_remove (cwh_head,
226 cwh_tail,
227 cwh);
228 GNUNET_free (cwh);
229 if (NULL != cwh_head)
230 return;
231 child_management_done ();
232}