From: Sree Harsha Totakura Date: Tue, 24 Jul 2012 13:46:12 +0000 (+0000) Subject: fixed mem leaks with operations X-Git-Tag: initial-import-from-subversion-38251~12360 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=8b9b2ab39943070706515485cff6e23cbb564003;p=oweals%2Fgnunet.git fixed mem leaks with operations --- diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c index ba026cb65..0d2a9d677 100644 --- a/src/testbed/test_testbed_api.c +++ b/src/testbed/test_testbed_api.c @@ -180,6 +180,7 @@ controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event) event->details.operation_finished.pit); GNUNET_assert (NULL != event->details.operation_finished.op_result.cfg); sub_test = PEER_DESTROY; + GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_destroy (peer); break; case PEER_DESTROY: @@ -190,6 +191,7 @@ controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event) event->details.operation_finished.pit); GNUNET_assert (NULL == event->details.operation_finished.op_result.generic); + GNUNET_TESTBED_operation_done (operation); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); break; case OTHER: @@ -200,12 +202,14 @@ controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event) case GNUNET_TESTBED_ET_PEER_START: GNUNET_assert (event->details.peer_start.host == host); GNUNET_assert (event->details.peer_start.peer == peer); + GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_stop (peer); break; case GNUNET_TESTBED_ET_PEER_STOP: GNUNET_assert (event->details.peer_stop.peer == peer); result = GNUNET_YES; sub_test = PEER_GETCONFIG; + GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_get_information (peer, GNUNET_TESTBED_PIT_CONFIGURATION); @@ -235,6 +239,7 @@ peer_create_cb (void *cls, GNUNET_assert (NULL != peer); GNUNET_assert (NULL != peer_ptr); *peer_ptr = peer; + GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_start (peer); GNUNET_assert (NULL != operation); } diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c index 6fce5adde..708fc1d04 100644 --- a/src/testbed/testbed_api.c +++ b/src/testbed/testbed_api.c @@ -267,14 +267,14 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c, } GNUNET_free (data->peer); GNUNET_free (data); + op->data = NULL; //PEERDESTROYDATA } break; default: - GNUNET_break (0); + GNUNET_assert (0); } GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); - GNUNET_free (op); if (NULL != event) { if (NULL != c->cc) @@ -327,9 +327,9 @@ handle_peer_create_success (struct GNUNET_TESTBED_Controller *c, GNUNET_assert (peer->unique_id == ntohl (msg->peer_id)); cb = data->cb; cls = data->cls; - GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); GNUNET_free (data); - GNUNET_free (op); + op->data = NULL; + GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); if (NULL != cb) cb (cls, peer, NULL); return GNUNET_YES; @@ -382,9 +382,8 @@ handle_peer_event (struct GNUNET_TESTBED_Controller *c, break; default: GNUNET_assert (0); /* We should never reach this state */ - } + } GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); - GNUNET_free (op); if (0 != ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) & c->event_mask)) { @@ -411,6 +410,7 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c, struct GNUNET_TESTBED_Operation *op; struct GNUNET_TESTBED_Peer *peer; struct PeerInfoData *data; + struct PeerInfoData2 *response_data; struct GNUNET_TESTBED_EventInformation info; uint64_t op_id; @@ -432,24 +432,28 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c, GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id); if (0 == (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) { + LOG_DEBUG ("Skipping operation callback as flag not set\n"); GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); - GNUNET_free (data); - GNUNET_free (op); return GNUNET_YES; } + response_data = GNUNET_malloc (sizeof (struct PeerInfoData2)); + response_data->pit = data->pit; + GNUNET_free (data); info.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; info.details.operation_finished.operation = op; info.details.operation_finished.op_cls = NULL; info.details.operation_finished.emsg = NULL; - info.details.operation_finished.pit = data->pit; - switch (data->pit) + info.details.operation_finished.pit = response_data->pit; + switch (response_data->pit) { case GNUNET_TESTBED_PIT_IDENTITY: { struct GNUNET_PeerIdentity *peer_identity; peer_identity = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); - (void) memcpy (peer_identity, &msg->peer_identity, sizeof (struct GNUNET_PeerIdentity)); + (void) memcpy (peer_identity, &msg->peer_identity, + sizeof (struct GNUNET_PeerIdentity)); + response_data->details.peer_identity = peer_identity; info.details.operation_finished.op_result.pid = peer_identity; } break; @@ -474,6 +478,7 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c, (size_t) config_size, GNUNET_NO)); GNUNET_free (config); + response_data->details.cfg = cfg; info.details.operation_finished.op_result.cfg = cfg; } break; @@ -481,10 +486,9 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c, GNUNET_assert (0); /* never reach here */ break; } - c->cc (c->cc_cls, &info); + op->data = response_data; GNUNET_CONTAINER_DLL_remove (c->op_head, c->op_tail, op); - GNUNET_free (data); - GNUNET_free (op); + c->cc (c->cc_cls, &info); return GNUNET_YES; } @@ -545,7 +549,9 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg) sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage)); status = handle_peer_config - (c, (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg); + (c, (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) + msg); + break; default: GNUNET_break (0); } @@ -1295,4 +1301,71 @@ GNUNET_TESTBED_create_helper_init_msg_ (const char *cname, } +/** + * Cancel a pending operation. Releases all resources + * of the operation and will ensure that no event + * is generated for the operation. Does NOT guarantee + * that the operation will be fully undone (or that + * nothing ever happened). + * + * @param operation operation to cancel + */ +void +GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation) +{ + GNUNET_CONTAINER_DLL_remove (operation->controller->op_head, + operation->controller->op_tail, + operation); + GNUNET_TESTBED_operation_done (operation); +} + + +/** + * Signal that the information from an operation has been fully + * processed. This function MUST be called for each event + * of type 'operation_finished' to fully remove the operation + * from the operation queue. After calling this function, the + * 'op_result' becomes invalid (!). + * + * @param operation operation to signal completion for + */ +void +GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) +{ + switch (operation->type) + { + case OP_PEER_CREATE: + GNUNET_free_non_null (operation->data); + break; + case OP_PEER_DESTROY: + GNUNET_free_non_null (operation->data); + break; + case OP_PEER_START: + case OP_PEER_STOP: + break; + case OP_PEER_INFO: + { + struct PeerInfoData2 *data; + + data = operation->data; + switch (data->pit) + { + case GNUNET_TESTBED_PIT_IDENTITY: + GNUNET_free (data->details.peer_identity); + break; + case GNUNET_TESTBED_PIT_CONFIGURATION: + GNUNET_CONFIGURATION_destroy (data->details.cfg); + break; + case GNUNET_TESTBED_PIT_GENERIC: + GNUNET_assert (0); /* never reach here */ + break; + } + } + GNUNET_free_non_null (operation->data); + break; + } + GNUNET_free (operation); +} + + /* end of testbed_api.c */ diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h index fcfb5008c..1d984ca93 100644 --- a/src/testbed/testbed_api.h +++ b/src/testbed/testbed_api.h @@ -75,6 +75,11 @@ struct GNUNET_TESTBED_Operation */ struct GNUNET_TESTBED_Operation *prev; + /** + * The controller on which this operation operates + */ + struct GNUNET_TESTBED_Controller *controller; + /** * The ID for the operation; */ diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c index c98998bbf..31a46d85a 100644 --- a/src/testbed/testbed_api_operations.c +++ b/src/testbed/testbed_api_operations.c @@ -146,49 +146,12 @@ GNUNET_TESTBED_operation_queue_remove_ (struct OperationQueue *queue, * * @param operation operation that finished */ -static void -operation_release (struct GNUNET_TESTBED_Operation *operation) -{ - // call operation->release, remove from queues - GNUNET_break (0); -} - - -/** - * Cancel a pending operation. Releases all resources - * of the operation and will ensure that no event - * is generated for the operation. Does NOT guarantee - * that the operation will be fully undone (or that - * nothing ever happened). - * - * @param operation operation to cancel - */ -void -GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation) -{ - // test that operation had not yet generated an event - GNUNET_break (0); - operation_release (operation); -} - - -/** - * Signal that the information from an operation has been fully - * processed. This function MUST be called for each event - * of type 'operation_finished' to fully remove the operation - * from the operation queue. After calling this function, the - * 'op_result' becomes invalid (!). - * - * @param operation operation to signal completion for - */ void -GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) +operation_release_ (struct GNUNET_TESTBED_Operation *operation) { - // test that operation was started and had generated an event + // call operation->release, remove from queues GNUNET_break (0); - operation_release (operation); } - /* end of testbed_api_operations.c */ diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h index 4c888d52d..5edca152d 100644 --- a/src/testbed/testbed_api_operations.h +++ b/src/testbed/testbed_api_operations.h @@ -128,5 +128,15 @@ GNUNET_TESTBED_operation_create_ (void *cls, ...); +/** + * An operation is 'done' (was cancelled or finished); remove + * it from the queues and release associated resources. + * + * @param operation operation that finished + */ +void +operation_release_ (struct GNUNET_TESTBED_Operation *operation); + + #endif /* end of testbed_api_operations.h */ diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c index c2bf2107f..4711aba7d 100644 --- a/src/testbed/testbed_api_peers.c +++ b/src/testbed/testbed_api_peers.c @@ -103,6 +103,7 @@ GNUNET_TESTBED_peer_create_with_id_ (uint32_t unique_id, data->cls = cls; data->peer = peer; op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); + op->controller = controller; op->operation_id = controller->operation_counter++; op->type = OP_PEER_CREATE; op->data = data; @@ -185,6 +186,7 @@ GNUNET_TESTBED_peer_start (struct GNUNET_TESTBED_Peer *peer) op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); op->operation_id = peer->controller->operation_counter++; + op->controller = peer->controller; op->type = OP_PEER_START; op->data = peer; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerStartMessage)); @@ -215,6 +217,7 @@ GNUNET_TESTBED_peer_stop (struct GNUNET_TESTBED_Peer *peer) op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); op->operation_id = peer->controller->operation_counter++; + op->controller = peer->controller; op->type = OP_PEER_STOP; op->data = peer; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerStopMessage)); @@ -251,6 +254,7 @@ GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer, op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); op->type = OP_PEER_INFO; op->operation_id = peer->controller->operation_counter++; + op->controller = peer->controller; op->data = data; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); @@ -304,6 +308,7 @@ GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer) data->peer = peer; op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); op->operation_id = peer->controller->operation_counter++; + op->controller = peer->controller; op->type = OP_PEER_DESTROY; op->data = data; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)); diff --git a/src/testbed/testbed_api_peers.h b/src/testbed/testbed_api_peers.h index 5b0a23c64..b3a74eef7 100644 --- a/src/testbed/testbed_api_peers.h +++ b/src/testbed/testbed_api_peers.h @@ -132,6 +132,34 @@ struct PeerInfoData }; +/** + * Data for the OperationType OP_PEER_INFO + */ +struct PeerInfoData2 +{ + /** + * The type of peer information requested + */ + enum GNUNET_TESTBED_PeerInformationType pit; + + /** + * The data from reply + */ + union + { + /** + * Configuration handle + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Peer Identity + */ + struct GNUNET_PeerIdentity *peer_identity; + } details; +}; + + /** * Create the given peer at the specified host using the given * controller. If the given controller is not running on the target