diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-28 16:01:51 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-28 16:01:51 +0000 |
commit | 8f8e6a5bb1ccbb7d1311332ec1cc3a340bdd621f (patch) | |
tree | fe7b589202e626a013b48050bd087a330efa1f1b /src/testbed | |
parent | 4a77d5e8ecf53f7fb2f54545d7c4313b3bcd7c05 (diff) | |
download | gnunet-8f8e6a5bb1ccbb7d1311332ec1cc3a340bdd621f.tar.gz gnunet-8f8e6a5bb1ccbb7d1311332ec1cc3a340bdd621f.zip |
- fix crashes in testbed_api_testbed upon interrupts
Diffstat (limited to 'src/testbed')
-rw-r--r-- | src/testbed/test_testbed_api_test.c | 2 | ||||
-rw-r--r-- | src/testbed/testbed_api.c | 10 | ||||
-rw-r--r-- | src/testbed/testbed_api_testbed.c | 96 |
3 files changed, 74 insertions, 34 deletions
diff --git a/src/testbed/test_testbed_api_test.c b/src/testbed/test_testbed_api_test.c index 705f52fa3..464d07b54 100644 --- a/src/testbed/test_testbed_api_test.c +++ b/src/testbed/test_testbed_api_test.c | |||
@@ -112,7 +112,7 @@ do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
112 | abort_task = GNUNET_SCHEDULER_NO_TASK; | 112 | abort_task = GNUNET_SCHEDULER_NO_TASK; |
113 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | 113 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) |
114 | GNUNET_SCHEDULER_cancel (shutdown_task); | 114 | GNUNET_SCHEDULER_cancel (shutdown_task); |
115 | shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL); | 115 | do_shutdown (cls, tc); |
116 | } | 116 | } |
117 | 117 | ||
118 | 118 | ||
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c index 25ed1ab41..e85fbb8f1 100644 --- a/src/testbed/testbed_api.c +++ b/src/testbed/testbed_api.c | |||
@@ -2073,10 +2073,16 @@ oprelease_shutdown_peers (void *cls) | |||
2073 | { | 2073 | { |
2074 | struct OperationContext *opc = cls; | 2074 | struct OperationContext *opc = cls; |
2075 | 2075 | ||
2076 | if (OPC_STATE_FINISHED != opc->state) | 2076 | switch (opc->state) |
2077 | { | 2077 | { |
2078 | GNUNET_free (opc->data); | 2078 | case OPC_STATE_STARTED: |
2079 | GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); | 2079 | GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); |
2080 | /* no break; continue */ | ||
2081 | case OPC_STATE_INIT: | ||
2082 | GNUNET_free (opc->data); | ||
2083 | break; | ||
2084 | case OPC_STATE_FINISHED: | ||
2085 | break; | ||
2080 | } | 2086 | } |
2081 | GNUNET_free (opc); | 2087 | GNUNET_free (opc); |
2082 | } | 2088 | } |
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c index bceda19a3..948cf4d55 100644 --- a/src/testbed/testbed_api_testbed.c +++ b/src/testbed/testbed_api_testbed.c | |||
@@ -239,6 +239,11 @@ struct RunContext | |||
239 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | 239 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; |
240 | 240 | ||
241 | /** | 241 | /** |
242 | * Task run upon shutdown interrupts | ||
243 | */ | ||
244 | GNUNET_SCHEDULER_TaskIdentifier interrupt_task; | ||
245 | |||
246 | /** | ||
242 | * The event mask for the controller | 247 | * The event mask for the controller |
243 | */ | 248 | */ |
244 | uint64_t event_mask; | 249 | uint64_t event_mask; |
@@ -327,24 +332,12 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
327 | GNUNET_free (rc); | 332 | GNUNET_free (rc); |
328 | } | 333 | } |
329 | 334 | ||
330 | |||
331 | /** | ||
332 | * Stops the testbed run and releases any used resources | ||
333 | * | ||
334 | * @param cls the tesbed run handle | ||
335 | * @param tc the task context from scheduler | ||
336 | */ | ||
337 | static void | 335 | static void |
338 | shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 336 | cleanup (struct RunContext *rc) |
339 | { | 337 | { |
340 | struct RunContext *rc = cls; | ||
341 | struct DLLOperation *dll_op; | 338 | struct DLLOperation *dll_op; |
342 | unsigned int nhost; | 339 | unsigned int nhost; |
343 | 340 | ||
344 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task); | ||
345 | rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK; | ||
346 | GNUNET_assert (GNUNET_NO == rc->shutdown); | ||
347 | rc->shutdown = GNUNET_YES; | ||
348 | if (NULL != rc->hc_handles) | 341 | if (NULL != rc->hc_handles) |
349 | { | 342 | { |
350 | for (nhost = 0; nhost < rc->num_hosts; nhost++) | 343 | for (nhost = 0; nhost < rc->num_hosts; nhost++) |
@@ -364,34 +357,55 @@ shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
364 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | 357 | GNUNET_SCHEDULER_cancel (rc->timeout_task); |
365 | rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 358 | rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
366 | } | 359 | } |
360 | if (GNUNET_SCHEDULER_NO_TASK != rc->interrupt_task) | ||
361 | { | ||
362 | GNUNET_SCHEDULER_cancel (rc->interrupt_task); | ||
363 | rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; | ||
364 | } | ||
367 | if (NULL != rc->reg_handle) | 365 | if (NULL != rc->reg_handle) |
368 | { | 366 | { |
369 | GNUNET_TESTBED_cancel_registration (rc->reg_handle); | 367 | GNUNET_TESTBED_cancel_registration (rc->reg_handle); |
370 | rc->reg_handle = NULL; | 368 | rc->reg_handle = NULL; |
371 | } | 369 | } |
370 | if (NULL != rc->topology_operation) | ||
371 | { | ||
372 | GNUNET_TESTBED_operation_done (rc->topology_operation); | ||
373 | rc->topology_operation = NULL; | ||
374 | } | ||
372 | /* cancel any exiting operations */ | 375 | /* cancel any exiting operations */ |
373 | if (NULL != rc->dll_op_head) | 376 | while (NULL != (dll_op = rc->dll_op_head)) |
374 | { | 377 | { |
375 | while (NULL != (dll_op = rc->dll_op_head)) | 378 | GNUNET_TESTBED_operation_done (dll_op->op); |
376 | { | 379 | GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op); |
377 | GNUNET_TESTBED_operation_done (dll_op->op); | 380 | GNUNET_free (dll_op); |
378 | GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op); | ||
379 | GNUNET_free (dll_op); | ||
380 | } | ||
381 | } | 381 | } |
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * Stops the testbed run and releases any used resources | ||
387 | * | ||
388 | * @param cls the tesbed run handle | ||
389 | * @param tc the task context from scheduler | ||
390 | */ | ||
391 | static void | ||
392 | shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
393 | { | ||
394 | struct RunContext *rc = cls; | ||
395 | struct DLLOperation *dll_op; | ||
396 | |||
397 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task); | ||
398 | rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK; | ||
399 | GNUNET_assert (GNUNET_NO == rc->shutdown); | ||
400 | rc->shutdown = GNUNET_YES; | ||
401 | cleanup (rc); | ||
382 | if (NULL != rc->c) | 402 | if (NULL != rc->c) |
383 | { | 403 | { |
384 | if (NULL != rc->peers) | 404 | if (NULL != rc->peers) |
385 | { | 405 | { |
386 | if (NULL != rc->topology_operation) | ||
387 | { | ||
388 | GNUNET_TESTBED_operation_done (rc->topology_operation); | ||
389 | rc->topology_operation = NULL; | ||
390 | } | ||
391 | if (RC_INIT == rc->state) | ||
392 | rc->state = RC_READY; /* Even though we haven't called the master callback */ | ||
393 | dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); | 406 | dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); |
394 | dll_op->op = GNUNET_TESTBED_shutdown_peers (rc->c, dll_op, NULL, NULL); | 407 | dll_op->op = GNUNET_TESTBED_shutdown_peers (rc->c, dll_op, NULL, NULL); |
408 | GNUNET_assert (NULL != dll_op->op); | ||
395 | DEBUG ("Shutting down peers\n"); | 409 | DEBUG ("Shutting down peers\n"); |
396 | rc->pstart_time = GNUNET_TIME_absolute_get (); | 410 | rc->pstart_time = GNUNET_TIME_absolute_get (); |
397 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, | 411 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, |
@@ -422,6 +436,16 @@ shutdown_now (struct RunContext *rc) | |||
422 | } | 436 | } |
423 | 437 | ||
424 | 438 | ||
439 | static void | ||
440 | interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
441 | { | ||
442 | struct RunContext *rc = cls; | ||
443 | |||
444 | rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; | ||
445 | shutdown_now (rc); | ||
446 | } | ||
447 | |||
448 | |||
425 | /** | 449 | /** |
426 | * Function to return the string representation of the duration between current | 450 | * Function to return the string representation of the duration between current |
427 | * time and `pstart_time' in `RunContext' | 451 | * time and `pstart_time' in `RunContext' |
@@ -458,6 +482,7 @@ start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
458 | { | 482 | { |
459 | dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); | 483 | dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); |
460 | dll_op->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); | 484 | dll_op->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); |
485 | GNUNET_assert (NULL != dll_op->op); | ||
461 | dll_op->cls = rc->peers[peer]; | 486 | dll_op->cls = rc->peers[peer]; |
462 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op); | 487 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op); |
463 | } | 488 | } |
@@ -568,7 +593,8 @@ create_peers (struct RunContext *rc) | |||
568 | (0 == | 593 | (0 == |
569 | rc->num_hosts) ? rc->h : rc->hosts[peer % | 594 | rc->num_hosts) ? rc->h : rc->hosts[peer % |
570 | rc->num_hosts], | 595 | rc->num_hosts], |
571 | rc->cfg, peer_create_cb, dll_op); | 596 | rc->cfg, peer_create_cb, dll_op); |
597 | GNUNET_assert (NULL != dll_op->op); | ||
572 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op); | 598 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op); |
573 | } | 599 | } |
574 | } | 600 | } |
@@ -778,6 +804,7 @@ register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
778 | dll_op->op = | 804 | dll_op->op = |
779 | GNUNET_TESTBED_controller_link (dll_op, rc->c, rc->hosts[slave], | 805 | GNUNET_TESTBED_controller_link (dll_op, rc->c, rc->hosts[slave], |
780 | rc->h, rc->cfg, GNUNET_YES); | 806 | rc->h, rc->cfg, GNUNET_YES); |
807 | GNUNET_assert (NULL != dll_op->op); | ||
781 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, | 808 | GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, |
782 | dll_op); | 809 | dll_op); |
783 | } | 810 | } |
@@ -812,12 +839,19 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
812 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 839 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
813 | _("Controller crash detected. Shutting down.\n")); | 840 | _("Controller crash detected. Shutting down.\n")); |
814 | rc->cproc = NULL; | 841 | rc->cproc = NULL; |
842 | cleanup (rc); | ||
815 | if (NULL != rc->peers) | 843 | if (NULL != rc->peers) |
816 | { | 844 | { |
817 | GNUNET_free (rc->peers); | 845 | GNUNET_free (rc->peers); |
818 | rc->peers = NULL; | 846 | rc->peers = NULL; |
819 | } | 847 | } |
820 | shutdown_now (rc); | 848 | if (GNUNET_YES == rc->shutdown) |
849 | { | ||
850 | rc->state = RC_PEERS_SHUTDOWN; | ||
851 | GNUNET_SCHEDULER_add_now (&cleanup_task, rc); | ||
852 | } | ||
853 | else | ||
854 | shutdown_now (rc); | ||
821 | return; | 855 | return; |
822 | } | 856 | } |
823 | GNUNET_CONFIGURATION_destroy (rc->cfg); | 857 | GNUNET_CONFIGURATION_destroy (rc->cfg); |
@@ -1140,8 +1174,8 @@ GNUNET_TESTBED_run (const char *host_filename, | |||
1140 | } | 1174 | } |
1141 | rc->timeout_task = | 1175 | rc->timeout_task = |
1142 | GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc); | 1176 | GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc); |
1143 | rc->shutdown_run_task = | 1177 | rc->interrupt_task = |
1144 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_run, | 1178 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, |
1145 | rc); | 1179 | rc); |
1146 | return; | 1180 | return; |
1147 | 1181 | ||