aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-03-28 16:01:51 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-03-28 16:01:51 +0000
commit8f8e6a5bb1ccbb7d1311332ec1cc3a340bdd621f (patch)
treefe7b589202e626a013b48050bd087a330efa1f1b /src/testbed
parent4a77d5e8ecf53f7fb2f54545d7c4313b3bcd7c05 (diff)
downloadgnunet-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.c2
-rw-r--r--src/testbed/testbed_api.c10
-rw-r--r--src/testbed/testbed_api_testbed.c96
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 */
337static void 335static void
338shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 336cleanup (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 */
391static void
392shutdown_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
439static void
440interrupt (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