aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-03-22 17:29:55 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-03-22 17:29:55 +0000
commit77164127c13ea285b40d2543de36d042fbc862c8 (patch)
treea0cd96bb4d87205f95d9d8b3eba079965a6316d3 /src/testbed
parentb9d47fab2e69e34326ec67bcf1144db45aef5b58 (diff)
downloadgnunet-77164127c13ea285b40d2543de36d042fbc862c8.tar.gz
gnunet-77164127c13ea285b40d2543de36d042fbc862c8.zip
- warn when operations are not freed where they could have been freed
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/testbed_api.c143
-rw-r--r--src/testbed/testbed_api_peers.c1
2 files changed, 116 insertions, 28 deletions
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index 11b2aae35..f806446cf 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -166,7 +166,76 @@ struct ShutdownPeersData
166 * 166 *
167 * This variable should ONLY be used to compare; it is a dangling pointer!! 167 * This variable should ONLY be used to compare; it is a dangling pointer!!
168 */ 168 */
169static const struct GNUNET_TESTBED_Operation *last_finished_operation; 169static const struct GNUNET_TESTBED_Operation *const last_finished_operation_;
170
171
172/**
173 * An entry in the stack for keeping operations which are about to expire
174 */
175struct ExpireOperationEntry
176{
177 /**
178 * DLL head; new entries are to be inserted here
179 */
180 struct ExpireOperationEntry *next;
181
182 /**
183 * DLL tail; entries are deleted from here
184 */
185 struct ExpireOperationEntry *prev;
186
187 /**
188 * The operation. This will be a dangling pointer when the operation is freed
189 */
190 const struct GNUNET_TESTBED_Operation *op;
191};
192
193static struct ExpireOperationEntry *exop_head;
194
195static struct ExpireOperationEntry *exop_tail;
196
197
198static void
199exop_insert (struct GNUNET_TESTBED_Operation *op)
200{
201 struct ExpireOperationEntry *entry;
202
203 entry = GNUNET_malloc (sizeof (struct ExpireOperationEntry));
204 entry->op = op;
205 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
206}
207
208
209static int
210exop_check (const struct GNUNET_TESTBED_Operation *const op)
211{
212 struct ExpireOperationEntry *entry;
213 struct ExpireOperationEntry *entry2;
214 int found;
215
216 found = GNUNET_NO;
217 entry = exop_head;
218 while (NULL != entry)
219 {
220 if (op == entry->op)
221 {
222 found = GNUNET_YES;
223 break;
224 }
225 entry = entry->next;
226 }
227 if (GNUNET_NO == found)
228 return GNUNET_NO;
229 /* Truncate the tail */
230 while (NULL != entry)
231 {
232 entry2 = entry->next;
233 GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
234 GNUNET_free (entry);
235 entry = entry2;
236 }
237 return GNUNET_YES;
238}
170 239
171 240
172/** 241/**
@@ -229,6 +298,8 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
229 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg) 298 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
230{ 299{
231 struct OperationContext *opc; 300 struct OperationContext *opc;
301 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
302 void *op_comp_cb_cls;
232 struct GNUNET_TESTBED_EventInformation event; 303 struct GNUNET_TESTBED_EventInformation event;
233 uint64_t op_id; 304 uint64_t op_id;
234 305
@@ -244,6 +315,8 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
244 event.op_cls = opc->op_cls; 315 event.op_cls = opc->op_cls;
245 event.details.operation_finished.emsg = NULL; 316 event.details.operation_finished.emsg = NULL;
246 event.details.operation_finished.generic = NULL; 317 event.details.operation_finished.generic = NULL;
318 op_comp_cb = NULL;
319 op_comp_cb_cls = NULL;
247 switch (opc->type) 320 switch (opc->type)
248 { 321 {
249 case OP_FORWARDED: 322 case OP_FORWARDED:
@@ -269,7 +342,9 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
269 struct ShutdownPeersData *data; 342 struct ShutdownPeersData *data;
270 343
271 data = opc->data; 344 data = opc->data;
272 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */ 345 op_comp_cb = data->cb;
346 op_comp_cb_cls = data->cb_cls;
347 GNUNET_free (data);
273 opc->data = NULL; 348 opc->data = NULL;
274 GNUNET_TESTBED_cleanup_peers_ (); 349 GNUNET_TESTBED_cleanup_peers_ ();
275 } 350 }
@@ -279,13 +354,20 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
279 } 354 }
280 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 355 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
281 opc->state = OPC_STATE_FINISHED; 356 opc->state = OPC_STATE_FINISHED;
357 exop_insert (event.op);
282 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) 358 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
283 { 359 {
284 if (NULL != c->cc) 360 if (NULL != c->cc)
285 c->cc (c->cc_cls, &event); 361 c->cc (c->cc_cls, &event);
362 if (GNUNET_NO == exop_check (event.op)) //(last_finished_operation == event.op)
363 return GNUNET_YES;
286 } 364 }
287 else 365 else
288 LOG_DEBUG ("Not calling callback\n"); 366 LOG_DEBUG ("Not calling callback\n");
367 if (NULL != op_comp_cb)
368 op_comp_cb (op_comp_cb_cls, event.op, NULL);
369 /* You could have marked the operation as done by now */
370 GNUNET_break (GNUNET_NO == exop_check (event.op)); //(last_finished_operation == event.op);
289 return GNUNET_YES; 371 return GNUNET_YES;
290} 372}
291 373
@@ -307,6 +389,7 @@ handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
307 struct OperationContext *opc; 389 struct OperationContext *opc;
308 struct PeerCreateData *data; 390 struct PeerCreateData *data;
309 struct GNUNET_TESTBED_Peer *peer; 391 struct GNUNET_TESTBED_Peer *peer;
392 struct GNUNET_TESTBED_Operation *op;
310 GNUNET_TESTBED_PeerCreateCallback cb; 393 GNUNET_TESTBED_PeerCreateCallback cb;
311 void *cls; 394 void *cls;
312 uint64_t op_id; 395 uint64_t op_id;
@@ -335,11 +418,15 @@ handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
335 GNUNET_TESTBED_peer_register_ (peer); 418 GNUNET_TESTBED_peer_register_ (peer);
336 cb = data->cb; 419 cb = data->cb;
337 cls = data->cls; 420 cls = data->cls;
421 op = opc->op;
338 GNUNET_free (opc->data); 422 GNUNET_free (opc->data);
339 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 423 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
340 opc->state = OPC_STATE_FINISHED; 424 opc->state = OPC_STATE_FINISHED;
425 exop_insert (op);
341 if (NULL != cb) 426 if (NULL != cb)
342 cb (cls, peer, NULL); 427 cb (cls, peer, NULL);
428 /* You could have marked the operation as done by now */
429 GNUNET_break (GNUNET_NO == exop_check (op)); //(last_finished_operation == op);
343 return GNUNET_YES; 430 return GNUNET_YES;
344} 431}
345 432
@@ -406,15 +493,20 @@ handle_peer_event (struct GNUNET_TESTBED_Controller *c,
406 GNUNET_free (data); 493 GNUNET_free (data);
407 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 494 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
408 opc->state = OPC_STATE_FINISHED; 495 opc->state = OPC_STATE_FINISHED;
496 exop_insert (event.op);
409 if (0 != 497 if (0 !=
410 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) & 498 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
411 c->event_mask)) 499 c->event_mask))
412 { 500 {
413 if (NULL != c->cc) 501 if (NULL != c->cc)
414 c->cc (c->cc_cls, &event); 502 c->cc (c->cc_cls, &event);
503 if (GNUNET_NO == exop_check (event.op))
504 return GNUNET_YES;
415 } 505 }
416 if (NULL != pcc) 506 if (NULL != pcc)
417 pcc (pcc_cls, NULL); 507 pcc (pcc_cls, NULL);
508 /* You could have marked the operation as done by now */
509 GNUNET_break (GNUNET_NO == exop_check (event.op)); // (event.op == last_finished_operation);
418 return GNUNET_YES; 510 return GNUNET_YES;
419} 511}
420 512
@@ -476,15 +568,20 @@ handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
476 cb_cls = data->cb_cls; 568 cb_cls = data->cb_cls;
477 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 569 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
478 opc->state = OPC_STATE_FINISHED; 570 opc->state = OPC_STATE_FINISHED;
479 if (NULL != cb) 571 exop_insert (event.op);
480 cb (cb_cls, opc->op, NULL);
481 if (0 != 572 if (0 !=
482 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) & 573 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
483 c->event_mask)) 574 c->event_mask))
484 { 575 {
485 if (NULL != c->cc) 576 if (NULL != c->cc)
486 c->cc (c->cc_cls, &event); 577 c->cc (c->cc_cls, &event);
487 } 578 if (GNUNET_NO == exop_check (event.op)) //(event.op == last_finished_operation)
579 return GNUNET_YES;
580 }
581 if (NULL != cb)
582 cb (cb_cls, opc->op, NULL);
583 /* You could have marked the operation as done by now */
584 GNUNET_break (GNUNET_NO == exop_check (event.op)); //(event.op == last_finished_operation);
488 return GNUNET_YES; 585 return GNUNET_YES;
489} 586}
490 587
@@ -529,11 +626,12 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c,
529 GNUNET_assert (NULL != peer); 626 GNUNET_assert (NULL != peer);
530 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id); 627 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
531 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation)); 628 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
532 pinfo->pit = data->pit; 629 pinfo->pit = data->pit;
533 cb = data->cb; 630 cb = data->cb;
534 cb_cls = data->cb_cls; 631 cb_cls = data->cb_cls;
632 GNUNET_assert (NULL != cb);
535 GNUNET_free (data); 633 GNUNET_free (data);
536 opc->data = NULL; 634 opc->data = NULL;
537 switch (pinfo->pit) 635 switch (pinfo->pit)
538 { 636 {
539 case GNUNET_TESTBED_PIT_IDENTITY: 637 case GNUNET_TESTBED_PIT_IDENTITY:
@@ -552,8 +650,10 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c,
552 opc->data = pinfo; 650 opc->data = pinfo;
553 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 651 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
554 opc->state = OPC_STATE_FINISHED; 652 opc->state = OPC_STATE_FINISHED;
555 if (NULL != cb) 653 cb (cb_cls, opc->op, pinfo, NULL);
556 cb (cb_cls, opc->op, pinfo, NULL); 654 /* We dont check whether the operation is marked as done here as the
655 operation contains data (cfg/identify) which will be freed at a later point
656 */
557 return GNUNET_YES; 657 return GNUNET_YES;
558} 658}
559 659
@@ -612,8 +712,9 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
612 event.op_cls = opc->op_cls; 712 event.op_cls = opc->op_cls;
613 event.details.operation_finished.emsg = emsg; 713 event.details.operation_finished.emsg = emsg;
614 event.details.operation_finished.generic = NULL; 714 event.details.operation_finished.generic = NULL;
715 exop_insert (event.op);
615 c->cc (c->cc_cls, &event); 716 c->cc (c->cc_cls, &event);
616 if (event.op == last_finished_operation) 717 if (GNUNET_NO == exop_check (event.op)) //(event.op == last_finished_operation)
617 return GNUNET_YES; 718 return GNUNET_YES;
618 } 719 }
619 switch (opc->type) 720 switch (opc->type)
@@ -1782,22 +1883,6 @@ GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1782 1883
1783 1884
1784/** 1885/**
1785 * Cancel a pending operation. Releases all resources
1786 * of the operation and will ensure that no event
1787 * is generated for the operation. Does NOT guarantee
1788 * that the operation will be fully undone (or that
1789 * nothing ever happened).
1790 *
1791 * @param operation operation to cancel
1792 */
1793void
1794GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1795{
1796 GNUNET_TESTBED_operation_done (operation);
1797}
1798
1799
1800/**
1801 * Signal that the information from an operation has been fully 1886 * Signal that the information from an operation has been fully
1802 * processed. This function MUST be called for each event 1887 * processed. This function MUST be called for each event
1803 * of type 'operation_finished' to fully remove the operation 1888 * of type 'operation_finished' to fully remove the operation
@@ -1809,7 +1894,9 @@ GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1809void 1894void
1810GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) 1895GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1811{ 1896{
1812 last_finished_operation = operation; 1897 *((const struct GNUNET_TESTBED_Operation **) &last_finished_operation_) =
1898 operation;
1899 (void) exop_check (operation);
1813 GNUNET_TESTBED_operation_release_ (operation); 1900 GNUNET_TESTBED_operation_release_ (operation);
1814} 1901}
1815 1902
diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c
index b5a66cd5d..cbf2f2385 100644
--- a/src/testbed/testbed_api_peers.c
+++ b/src/testbed/testbed_api_peers.c
@@ -621,6 +621,7 @@ GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer,
621 struct PeerInfoData *data; 621 struct PeerInfoData *data;
622 622
623 GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit); 623 GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit);
624 GNUNET_assert (NULL != cb);
624 data = GNUNET_malloc (sizeof (struct PeerInfoData)); 625 data = GNUNET_malloc (sizeof (struct PeerInfoData));
625 data->peer = peer; 626 data->peer = peer;
626 data->pit = pit; 627 data->pit = pit;