diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-05-09 09:45:53 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-05-09 09:45:53 +0000 |
commit | efad1d6733cd7e75a4e6c846ad7c031a0167b8be (patch) | |
tree | 93c8d652b78ae04b5b4a5c8e1e8abe398d4dd8c7 /src/util/helper.c | |
parent | d96c9d244148f2ee984c206b71987ba6df0ec820 (diff) | |
download | gnunet-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/helper.c')
-rw-r--r-- | src/util/helper.c | 140 |
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 | */ |
171 | static void | 174 | int |
172 | stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill) | 175 | GNUNET_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 | */ | ||
219 | int | ||
220 | GNUNET_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 | */ | ||
275 | static void | ||
276 | stop_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 | */ |
454 | static void | 502 | void |
455 | kill_helper (struct GNUNET_HELPER_Handle *h, int soft_kill) | 503 | GNUNET_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 | */ |
486 | void | 523 | void |
487 | GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) | 524 | GNUNET_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 | */ | ||
499 | void | ||
500 | GNUNET_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); |