aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-05-09 09:45:53 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-05-09 09:45:53 +0000
commitefad1d6733cd7e75a4e6c846ad7c031a0167b8be (patch)
tree93c8d652b78ae04b5b4a5c8e1e8abe398d4dd8c7 /src/util
parentd96c9d244148f2ee984c206b71987ba6df0ec820 (diff)
downloadgnunet-efad1d6733cd7e75a4e6c846ad7c031a0167b8be.tar.gz
gnunet-efad1d6733cd7e75a4e6c846ad7c031a0167b8be.zip
- complement HELPER API with functions to kill and wait on the helper process
- To shutdown quickly, have testbed first kill all sub-controller's helper processes first and wait later instead of kill & wait per each processes.
Diffstat (limited to 'src/util')
-rw-r--r--src/util/helper.c140
1 files changed, 83 insertions, 57 deletions
diff --git a/src/util/helper.c b/src/util/helper.c
index d7a3cb271..57e5798d8 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -20,7 +20,8 @@
20 20
21/** 21/**
22 * @file util/helper.c 22 * @file util/helper.c
23 * @brief API for dealing with (SUID) helper processes that communicate via GNUNET_MessageHeaders on stdin/stdout 23 * @brief API for dealing with (SUID) helper processes that communicate via
24 * GNUNET_MessageHeaders on stdin/stdout
24 * @author Philipp Toelke 25 * @author Philipp Toelke
25 * @author Christian Grothoff 26 * @author Christian Grothoff
26 */ 27 */
@@ -162,38 +163,71 @@ struct GNUNET_HELPER_Handle
162 163
163 164
164/** 165/**
165 * Stop the helper process, we're closing down or had an error. 166 * Sends termination signal to the helper process. The helper process is not
167 * reaped; call GNUNET_HELPER_wait() for reaping the dead helper process.
166 * 168 *
167 * @param h handle to the helper process 169 * @param h the helper handle
168 * @param soft_kill if GNUNET_YES, signals termination by closing the helper's 170 * @param soft_kill if GNUNET_YES, signals termination by closing the helper's
169 * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper 171 * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper
172 * @return GNUNET_OK on success; GNUNET_SYSERR on error
170 */ 173 */
171static void 174int
172stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill) 175GNUNET_HELPER_kill (struct GNUNET_HELPER_Handle *h, int soft_kill)
173{ 176{
174 struct GNUNET_HELPER_SendHandle *sh; 177 struct GNUNET_HELPER_SendHandle *sh;
178 int ret;
175 179
176 if (NULL != h->helper_proc) 180 while (NULL != (sh = h->sh_head))
177 { 181 {
178 if (GNUNET_YES == soft_kill) 182 GNUNET_CONTAINER_DLL_remove (h->sh_head,
179 { 183 h->sh_tail,
180 /* soft-kill only possible with pipes */ 184 sh);
181 GNUNET_assert (NULL != h->helper_in); 185 if (NULL != sh->cont)
182 GNUNET_DISK_pipe_close (h->helper_in); 186 sh->cont (sh->cont_cls, GNUNET_NO);
183 h->helper_in = NULL; 187 GNUNET_free (sh);
184 h->fh_to_helper = NULL;
185 }
186 else
187 GNUNET_break (0 == GNUNET_OS_process_kill (h->helper_proc, SIGTERM));
188 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (h->helper_proc));
189 GNUNET_OS_process_destroy (h->helper_proc);
190 h->helper_proc = NULL;
191 } 188 }
192 if (GNUNET_SCHEDULER_NO_TASK != h->restart_task) 189 if (GNUNET_SCHEDULER_NO_TASK != h->restart_task)
193 { 190 {
194 GNUNET_SCHEDULER_cancel (h->restart_task); 191 GNUNET_SCHEDULER_cancel (h->restart_task);
195 h->restart_task = GNUNET_SCHEDULER_NO_TASK; 192 h->restart_task = GNUNET_SCHEDULER_NO_TASK;
196 } 193 }
194 if (NULL == h->helper_proc)
195 return GNUNET_SYSERR;
196 if (GNUNET_YES == soft_kill)
197 {
198 /* soft-kill only possible with pipes */
199 GNUNET_assert (NULL != h->helper_in);
200 ret = GNUNET_DISK_pipe_close (h->helper_in);
201 h->helper_in = NULL;
202 h->fh_to_helper = NULL;
203 return ret;
204 }
205 if (0 != GNUNET_OS_process_kill (h->helper_proc, SIGTERM))
206 return GNUNET_SYSERR;
207 return GNUNET_OK;
208}
209
210
211/**
212 * Reap the helper process. This call is blocking(!). The helper process
213 * should either be sent a termination signal before or should be dead before
214 * calling this function
215 *
216 * @param h the helper handle
217 * @return GNUNET_OK on success; GNUNET_SYSERR on error
218 */
219int
220GNUNET_HELPER_wait (struct GNUNET_HELPER_Handle *h)
221{
222 struct GNUNET_HELPER_SendHandle *sh;
223 int ret;
224
225 if (NULL != h->helper_proc)
226 {
227 ret = GNUNET_OS_process_wait (h->helper_proc);
228 GNUNET_OS_process_destroy (h->helper_proc);
229 h->helper_proc = NULL;
230 }
197 if (GNUNET_SCHEDULER_NO_TASK != h->read_task) 231 if (GNUNET_SCHEDULER_NO_TASK != h->read_task)
198 { 232 {
199 GNUNET_SCHEDULER_cancel (h->read_task); 233 GNUNET_SCHEDULER_cancel (h->read_task);
@@ -227,6 +261,22 @@ stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill)
227 } 261 }
228 /* purge MST buffer */ 262 /* purge MST buffer */
229 (void) GNUNET_SERVER_mst_receive (h->mst, NULL, NULL, 0, GNUNET_YES, GNUNET_NO); 263 (void) GNUNET_SERVER_mst_receive (h->mst, NULL, NULL, 0, GNUNET_YES, GNUNET_NO);
264 return ret;
265}
266
267
268/**
269 * Stop the helper process, we're closing down or had an error.
270 *
271 * @param h handle to the helper process
272 * @param soft_kill if GNUNET_YES, signals termination by closing the helper's
273 * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper
274 */
275static void
276stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill)
277{
278 GNUNET_break (GNUNET_OK == GNUNET_HELPER_kill (h, soft_kill));
279 GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (h));
230} 280}
231 281
232 282
@@ -274,7 +324,7 @@ helper_read (void *cls,
274 if (NULL != h->exp_cb) 324 if (NULL != h->exp_cb)
275 { 325 {
276 h->exp_cb (h->cb_cls); 326 h->exp_cb (h->cb_cls);
277 GNUNET_HELPER_stop (h); 327 GNUNET_HELPER_stop (h, GNUNET_NO);
278 return; 328 return;
279 } 329 }
280 stop_helper (h, GNUNET_NO); 330 stop_helper (h, GNUNET_NO);
@@ -293,7 +343,7 @@ helper_read (void *cls,
293 if (NULL != h->exp_cb) 343 if (NULL != h->exp_cb)
294 { 344 {
295 h->exp_cb (h->cb_cls); 345 h->exp_cb (h->cb_cls);
296 GNUNET_HELPER_stop (h); 346 GNUNET_HELPER_stop (h, GNUNET_NO);
297 return; 347 return;
298 } 348 }
299 stop_helper (h, GNUNET_NO); 349 stop_helper (h, GNUNET_NO);
@@ -318,7 +368,7 @@ helper_read (void *cls,
318 if (NULL != h->exp_cb) 368 if (NULL != h->exp_cb)
319 { 369 {
320 h->exp_cb (h->cb_cls); 370 h->exp_cb (h->cb_cls);
321 GNUNET_HELPER_stop (h); 371 GNUNET_HELPER_stop (h, GNUNET_NO);
322 return; 372 return;
323 } 373 }
324 stop_helper (h, GNUNET_NO); 374 stop_helper (h, GNUNET_NO);
@@ -445,30 +495,15 @@ GNUNET_HELPER_start (int with_control_pipe,
445 495
446 496
447/** 497/**
448 * @brief Kills the helper, closes the pipe and frees the h 498 * Free's the resources occupied by the helper handle
449 * 499 *
450 * @param h h to helper to stop 500 * @param h the helper handle to free
451 * @param soft_kill if GNUNET_YES, signals termination by closing the helper's
452 * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper
453 */ 501 */
454static void 502void
455kill_helper (struct GNUNET_HELPER_Handle *h, int soft_kill) 503GNUNET_HELPER_destroy (struct GNUNET_HELPER_Handle *h)
456{ 504{
457 struct GNUNET_HELPER_SendHandle *sh;
458 unsigned int c; 505 unsigned int c;
459 506
460 h->exp_cb = NULL;
461 /* signal pending writes that we were stopped */
462 while (NULL != (sh = h->sh_head))
463 {
464 GNUNET_CONTAINER_DLL_remove (h->sh_head,
465 h->sh_tail,
466 sh);
467 if (NULL != sh->cont)
468 sh->cont (sh->cont_cls, GNUNET_SYSERR);
469 GNUNET_free (sh);
470 }
471 stop_helper (h, soft_kill);
472 GNUNET_SERVER_mst_destroy (h->mst); 507 GNUNET_SERVER_mst_destroy (h->mst);
473 GNUNET_free (h->binary_name); 508 GNUNET_free (h->binary_name);
474 for (c = 0; h->binary_argv[c] != NULL; c++) 509 for (c = 0; h->binary_argv[c] != NULL; c++)
@@ -482,24 +517,15 @@ kill_helper (struct GNUNET_HELPER_Handle *h, int soft_kill)
482 * Kills the helper, closes the pipe and frees the handle 517 * Kills the helper, closes the pipe and frees the handle
483 * 518 *
484 * @param h handle to helper to stop 519 * @param h handle to helper to stop
520 * @param soft_kill if GNUNET_YES, signals termination by closing the helper's
521 * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper
485 */ 522 */
486void 523void
487GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) 524GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h, int soft_kill)
488{
489 kill_helper (h, GNUNET_NO);
490}
491
492
493/**
494 * Kills the helper by closing its stdin (the helper is expected to catch the
495 * resulting SIGPIPE and shutdown), closes the pipe and frees the handle
496 *
497 * @param h handle to helper to stop
498 */
499void
500GNUNET_HELPER_soft_stop (struct GNUNET_HELPER_Handle *h)
501{ 525{
502 kill_helper (h, GNUNET_YES); 526 h->exp_cb = NULL;
527 stop_helper (h, soft_kill);
528 GNUNET_HELPER_destroy (h);
503} 529}
504 530
505 531
@@ -540,7 +566,7 @@ helper_write (void *cls,
540 if (NULL != h->exp_cb) 566 if (NULL != h->exp_cb)
541 { 567 {
542 h->exp_cb (h->cb_cls); 568 h->exp_cb (h->cb_cls);
543 GNUNET_HELPER_stop (h); 569 GNUNET_HELPER_stop (h, GNUNET_NO);
544 return; 570 return;
545 } 571 }
546 stop_helper (h, GNUNET_NO); 572 stop_helper (h, GNUNET_NO);