aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/gnunet-helper-testbed.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-03-06 15:17:14 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-03-06 15:17:14 +0000
commit60d15a9c381f64552a963aa18a557874f3b5c280 (patch)
tree886b4df687aa489bc0d1bcbb7ce34c8e7534347c /src/testbed/gnunet-helper-testbed.c
parent48f89e668ca47d4538df015d1d6d309c4a0595ea (diff)
downloadgnunet-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.c84
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;
109static struct GNUNET_OS_Process *testbed; 109static struct GNUNET_OS_Process *testbed;
110 110
111/** 111/**
112 * Pipe used to communicate shutdown via signal.
113 */
114static struct GNUNET_DISK_PipeHandle *sigpipe;
115
116/**
112 * Task identifier for the read task 117 * Task identifier for the read task
113 */ 118 */
114static GNUNET_SCHEDULER_TaskIdentifier read_task_id; 119static GNUNET_SCHEDULER_TaskIdentifier read_task_id;
@@ -119,6 +124,11 @@ static GNUNET_SCHEDULER_TaskIdentifier read_task_id;
119static GNUNET_SCHEDULER_TaskIdentifier write_task_id; 124static GNUNET_SCHEDULER_TaskIdentifier write_task_id;
120 125
121/** 126/**
127 * Task to kill the child
128 */
129static 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 */
124static int done_reading; 134static 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 */
425static void
426child_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,
443static void 486static void
444sighandler_child_death () 487sighandler_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;