diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-22 17:29:55 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-03-22 17:29:55 +0000 |
commit | 77164127c13ea285b40d2543de36d042fbc862c8 (patch) | |
tree | a0cd96bb4d87205f95d9d8b3eba079965a6316d3 /src/testbed | |
parent | b9d47fab2e69e34326ec67bcf1144db45aef5b58 (diff) | |
download | gnunet-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.c | 143 | ||||
-rw-r--r-- | src/testbed/testbed_api_peers.c | 1 |
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 | */ |
169 | static const struct GNUNET_TESTBED_Operation *last_finished_operation; | 169 | static 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 | */ | ||
175 | struct 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 | |||
193 | static struct ExpireOperationEntry *exop_head; | ||
194 | |||
195 | static struct ExpireOperationEntry *exop_tail; | ||
196 | |||
197 | |||
198 | static void | ||
199 | exop_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 | |||
209 | static int | ||
210 | exop_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 | */ | ||
1793 | void | ||
1794 | GNUNET_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) | |||
1809 | void | 1894 | void |
1810 | GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) | 1895 | GNUNET_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; |