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.c243
1 files changed, 0 insertions, 243 deletions
diff --git a/src/util/child_management.c b/src/util/child_management.c
deleted file mode 100644
index 3afd682b9..000000000
--- a/src/util/child_management.c
+++ /dev/null
@@ -1,243 +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
95 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
96 "Received SIGCHLD.\n");
97
98 /* drain pipe */
99 pr = GNUNET_DISK_pipe_handle (sigpipe,
100 GNUNET_DISK_PIPE_END_READ);
101 GNUNET_assert (! GNUNET_DISK_handle_invalid (pr));
102
103 (void) GNUNET_DISK_file_read (pr,
104 buf,
105 sizeof(buf));
106
107 /* find applicable processes that exited */
108 for (struct GNUNET_ChildWaitHandle *cwh = cwh_head;
109 NULL != cwh;
110 cwh = nxt)
111 {
112 enum GNUNET_OS_ProcessStatusType type;
113 long unsigned int exit_code = 0;
114
115 nxt = cwh->next;
116 if (GNUNET_OK ==
117 GNUNET_OS_process_status (cwh->proc,
118 &type,
119 &exit_code))
120 {
121 GNUNET_CONTAINER_DLL_remove (cwh_head,
122 cwh_tail,
123 cwh);
124 cwh->cb (cwh->cb_cls,
125 type,
126 exit_code);
127 GNUNET_free (cwh);
128 }
129 }
130 if (NULL == cwh_head)
131 return;
132 /* wait for more */
133 sig_task = GNUNET_SCHEDULER_add_read_file (
134 GNUNET_TIME_UNIT_FOREVER_REL,
135 GNUNET_DISK_pipe_handle (sigpipe,
136 GNUNET_DISK_PIPE_END_READ),
137 &maint_child_death,
138 NULL);
139}
140
141
142/**
143 * Signal handler called for SIGCHLD. Triggers the
144 * respective handler by writing to the trigger pipe.
145 */
146static void
147sighandler_child_death (void)
148{
149 static char c;
150 int old_errno = errno; /* back-up errno */
151
152 GNUNET_break (
153 1 ==
154 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
155 GNUNET_DISK_PIPE_END_WRITE),
156 &c,
157 sizeof(c)));
158 errno = old_errno; /* restore errno */
159}
160
161
162// void __attribute__ ((constructor))
163static void
164child_management_start ()
165{
166 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
167 "Trying to start child management.\n");
168 if (NULL != sigpipe)
169 return; /* already initialized */
170 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
171 GNUNET_assert (sigpipe != NULL);
172 shc_chld =
173 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
174 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
175 "Child management started.\n");
176}
177
178/**
179 * Clean up.
180 */
181// void __attribute__ ((destructor))
182static void
183child_management_done ()
184{
185 GNUNET_assert (NULL == sig_task);
186 GNUNET_SIGNAL_handler_uninstall (shc_chld);
187 shc_chld = NULL;
188 GNUNET_DISK_pipe_close (sigpipe);
189 sigpipe = NULL;
190 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
191 "Child management stopped.\n");
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 LOG (GNUNET_ERROR_TYPE_ERROR,
202 "Adding child!\n");
203
204 child_management_start ();
205 cwh = GNUNET_new (struct GNUNET_ChildWaitHandle);
206 cwh->proc = proc;
207 cwh->cb = cb;
208 cwh->cb_cls = cb_cls;
209 GNUNET_CONTAINER_DLL_insert (cwh_head,
210 cwh_tail,
211 cwh);
212 if (NULL == sig_task)
213 {
214 sig_task = GNUNET_SCHEDULER_add_read_file (
215 GNUNET_TIME_UNIT_FOREVER_REL,
216 GNUNET_DISK_pipe_handle (sigpipe,
217 GNUNET_DISK_PIPE_END_READ),
218 &maint_child_death,
219 NULL);
220 }
221 return cwh;
222}
223
224void
225GNUNET_wait_child_cancel (struct GNUNET_ChildWaitHandle *cwh)
226{
227 if ((NULL != cwh_head))
228 {
229 GNUNET_CONTAINER_DLL_remove (cwh_head,
230 cwh_tail,
231 cwh);
232 }
233 if (NULL == cwh_head)
234 {
235 child_management_done ();
236 }
237 if (NULL != sig_task)
238 {
239 GNUNET_SCHEDULER_cancel (sig_task);
240 sig_task = NULL;
241 }
242 GNUNET_free (cwh);
243}