fixed mem leaks with operations
authorSree Harsha Totakura <totakura@in.tum.de>
Tue, 24 Jul 2012 13:46:12 +0000 (13:46 +0000)
committerSree Harsha Totakura <totakura@in.tum.de>
Tue, 24 Jul 2012 13:46:12 +0000 (13:46 +0000)
src/testbed/test_testbed_api.c
src/testbed/testbed_api.c
src/testbed/testbed_api.h
src/testbed/testbed_api_operations.c
src/testbed/testbed_api_operations.h
src/testbed/testbed_api_peers.c
src/testbed/testbed_api_peers.h

index ba026cb652fc62fb8f13bb075f46a49924049e55..0d2a9d6770b2088d00f0ccd5657e69f4607e38a9 100644 (file)
@@ -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);
 }
index 6fce5addecaa1f74dcb35a37370763939b675107..708fc1d04f0cf6776ee4d37661a85061f801ca7a 100644 (file)
@@ -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 */
index fcfb5008cf984eca5404a0ff9f65f5c4200dc75d..1d984ca933c37bde52b56c6daa16683626ada610 100644 (file)
@@ -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;
    */
index c98998bbffee4fa5cd5302c9ec4653a5680177fd..31a46d85a8059a0472c19c26042edaaf861edc45 100644 (file)
@@ -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 */
index 4c888d52d34a5fd26802e790a605ff4f051487a4..5edca152de9ca9881b6e3a288990a83ad9211f76 100644 (file)
@@ -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 */
index c2bf2107f1f5e0fef9e9f6118e954e2357fadd15..4711aba7d24c0629adabbe9661081668e3bebd38 100644 (file)
@@ -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));
index 5b0a23c64f0d04f169ce9bd9dfe33895773dfea5..b3a74eef7db520e24ed2f7daace6faf8326d846e 100644 (file)
@@ -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