diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-06 15:17:14 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-06 15:17:14 +0000 |
commit | 60d15a9c381f64552a963aa18a557874f3b5c280 (patch) | |
tree | 886b4df687aa489bc0d1bcbb7ce34c8e7534347c /src/testbed/gnunet-helper-testbed.c | |
parent | 48f89e668ca47d4538df015d1d6d309c4a0595ea (diff) | |
download | gnunet-60d15a9c381f64552a963aa18a557874f3b5c280.tar.gz gnunet-60d15a9c381f64552a963aa18a557874f3b5c280.zip |
Don't call gnunet scheduler from signal handler. Instead, write to a pipe
(ARM-style) to run a scheduler task when signal is received.
Diffstat (limited to 'src/testbed/gnunet-helper-testbed.c')
-rw-r--r-- | src/testbed/gnunet-helper-testbed.c | 84 |
1 files changed, 68 insertions, 16 deletions
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c index 7d0bf873d..e4b836396 100644 --- a/src/testbed/gnunet-helper-testbed.c +++ b/src/testbed/gnunet-helper-testbed.c | |||
@@ -109,6 +109,11 @@ static struct GNUNET_DISK_FileHandle *stdout_fd; | |||
109 | static struct GNUNET_OS_Process *testbed; | 109 | static struct GNUNET_OS_Process *testbed; |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * Pipe used to communicate shutdown via signal. | ||
113 | */ | ||
114 | static struct GNUNET_DISK_PipeHandle *sigpipe; | ||
115 | |||
116 | /** | ||
112 | * Task identifier for the read task | 117 | * Task identifier for the read task |
113 | */ | 118 | */ |
114 | static GNUNET_SCHEDULER_TaskIdentifier read_task_id; | 119 | static GNUNET_SCHEDULER_TaskIdentifier read_task_id; |
@@ -119,6 +124,11 @@ static GNUNET_SCHEDULER_TaskIdentifier read_task_id; | |||
119 | static GNUNET_SCHEDULER_TaskIdentifier write_task_id; | 124 | static GNUNET_SCHEDULER_TaskIdentifier write_task_id; |
120 | 125 | ||
121 | /** | 126 | /** |
127 | * Task to kill the child | ||
128 | */ | ||
129 | static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id; | ||
130 | |||
131 | /** | ||
122 | * Are we done reading messages from stdin? | 132 | * Are we done reading messages from stdin? |
123 | */ | 133 | */ |
124 | static int done_reading; | 134 | static int done_reading; |
@@ -166,14 +176,6 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
166 | { | 176 | { |
167 | LOG_DEBUG ("Killing testbed\n"); | 177 | LOG_DEBUG ("Killing testbed\n"); |
168 | GNUNET_break (0 == GNUNET_OS_process_kill (testbed, SIGTERM)); | 178 | GNUNET_break (0 == GNUNET_OS_process_kill (testbed, SIGTERM)); |
169 | GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (testbed)); | ||
170 | GNUNET_OS_process_destroy (testbed); | ||
171 | testbed = NULL; | ||
172 | } | ||
173 | if (NULL != test_system) | ||
174 | { | ||
175 | GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); | ||
176 | test_system = NULL; | ||
177 | } | 179 | } |
178 | } | 180 | } |
179 | 181 | ||
@@ -414,6 +416,42 @@ read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
414 | 416 | ||
415 | 417 | ||
416 | /** | 418 | /** |
419 | * Task triggered whenever we receive a SIGCHLD (child | ||
420 | * process died). | ||
421 | * | ||
422 | * @param cls closure, NULL if we need to self-restart | ||
423 | * @param tc context | ||
424 | */ | ||
425 | static void | ||
426 | child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
427 | { | ||
428 | const struct GNUNET_DISK_FileHandle *pr; | ||
429 | char c[16]; | ||
430 | |||
431 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | ||
432 | child_death_task_id = GNUNET_SCHEDULER_NO_TASK; | ||
433 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) | ||
434 | { | ||
435 | child_death_task_id = | ||
436 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
437 | pr, &child_death_task, NULL); | ||
438 | return; | ||
439 | } | ||
440 | /* consume the signal */ | ||
441 | GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); | ||
442 | LOG_DEBUG ("Child died\n"); | ||
443 | GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (testbed)); | ||
444 | GNUNET_OS_process_destroy (testbed); | ||
445 | testbed = NULL; | ||
446 | if (NULL != test_system) | ||
447 | { | ||
448 | GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); | ||
449 | test_system = NULL; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
417 | * Main function that will be run. | 455 | * Main function that will be run. |
418 | * | 456 | * |
419 | * @param cls closure | 457 | * @param cls closure |
@@ -434,6 +472,11 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
434 | &read_task, NULL); | 472 | &read_task, NULL); |
435 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | 473 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, |
436 | NULL); | 474 | NULL); |
475 | child_death_task_id = | ||
476 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
477 | GNUNET_DISK_pipe_handle (sigpipe, | ||
478 | GNUNET_DISK_PIPE_END_READ), | ||
479 | &child_death_task, NULL); | ||
437 | } | 480 | } |
438 | 481 | ||
439 | 482 | ||
@@ -443,14 +486,15 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
443 | static void | 486 | static void |
444 | sighandler_child_death () | 487 | sighandler_child_death () |
445 | { | 488 | { |
446 | if ((NULL != testbed) && (GNUNET_NO == in_shutdown)) | 489 | static char c; |
447 | { | 490 | int old_errno; /* back-up errno */ |
448 | LOG_DEBUG ("Child died\n"); | 491 | |
449 | GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (testbed)); | 492 | old_errno = errno; |
450 | GNUNET_OS_process_destroy (testbed); | 493 | GNUNET_break (1 == |
451 | testbed = NULL; | 494 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle |
452 | GNUNET_SCHEDULER_shutdown (); /* We are done too! */ | 495 | (sigpipe, GNUNET_DISK_PIPE_END_WRITE), |
453 | } | 496 | &c, sizeof (c))); |
497 | errno = old_errno; | ||
454 | } | 498 | } |
455 | 499 | ||
456 | 500 | ||
@@ -473,6 +517,13 @@ main (int argc, char **argv) | |||
473 | 517 | ||
474 | status = GNUNET_OK; | 518 | status = GNUNET_OK; |
475 | in_shutdown = GNUNET_NO; | 519 | in_shutdown = GNUNET_NO; |
520 | if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, | ||
521 | GNUNET_NO, GNUNET_NO))) | ||
522 | { | ||
523 | GNUNET_break (0); | ||
524 | ret = GNUNET_SYSERR; | ||
525 | return 1; | ||
526 | } | ||
476 | shc_chld = | 527 | shc_chld = |
477 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); | 528 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); |
478 | ret = | 529 | ret = |
@@ -481,6 +532,7 @@ main (int argc, char **argv) | |||
481 | &run, NULL); | 532 | &run, NULL); |
482 | GNUNET_SIGNAL_handler_uninstall (shc_chld); | 533 | GNUNET_SIGNAL_handler_uninstall (shc_chld); |
483 | shc_chld = NULL; | 534 | shc_chld = NULL; |
535 | GNUNET_DISK_pipe_close (sigpipe); | ||
484 | if (GNUNET_OK != ret) | 536 | if (GNUNET_OK != ret) |
485 | return 1; | 537 | return 1; |
486 | return (GNUNET_OK == status) ? 0 : 1; | 538 | return (GNUNET_OK == status) ? 0 : 1; |