gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r29028 - gnunet/src/scalarproduct


From: gnunet
Subject: [GNUnet-SVN] r29028 - gnunet/src/scalarproduct
Date: Thu, 5 Sep 2013 15:11:59 +0200

Author: cfuchs
Date: 2013-09-05 15:11:59 +0200 (Thu, 05 Sep 2013)
New Revision: 29028

Modified:
   gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
Log:
fixed dangling tasks in SP-service
removed destroy tunnel function, as it is no longer needed with new-mesh
tasks now get queued in a DLL and are removed from it upon execution. 
do_shutdown de-queues all outstanding tasks



Modified: gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
===================================================================
--- gnunet/src/scalarproduct/gnunet-service-scalarproduct.c     2013-09-05 
12:57:55 UTC (rev 29027)
+++ gnunet/src/scalarproduct/gnunet-service-scalarproduct.c     2013-09-05 
13:11:59 UTC (rev 29028)
@@ -160,7 +160,6 @@
      * tunnel-handle associated with our mesh handle
      */
     struct GNUNET_MESH_Tunnel * tunnel;
-
 };
 
 /**
@@ -180,6 +179,32 @@
     struct GNUNET_MessageHeader * msg;
 };
 
+/**
+ * Linked list for all queued tasks.
+ */
+struct TaskClosure
+{
+  
+  /**
+   * point to the next element of the list
+   */
+  struct TaskClosure *next;
+  
+  /**
+   * point to the previous element of the list
+   */
+  struct TaskClosure *prev;
+
+  /**
+   * the handle associated with this task, canceled upon shutdown
+   */
+  GNUNET_SCHEDULER_TaskIdentifier my_handle;
+  
+  /**
+   * the closure, as it's always a session-struct, we don't cast this to void
+   */
+  struct ServiceSession * my_session;
+};
 ///////////////////////////////////////////////////////////////////////////////
 //                      Global Variables
 ///////////////////////////////////////////////////////////////////////////////
@@ -267,6 +292,15 @@
  */
 static int do_shutdown;
 
+/**
+ * DLL for all out active, queued tasks. Purged upon disconnect
+ */
+static struct TaskClosure * tasklist_head;
+/**
+ * DLL for all out active, queued tasks. Purged upon disconnect
+ */
+static struct TaskClosure * tasklist_tail;
+
 ///////////////////////////////////////////////////////////////////////////////
 //                      Helper Functions
 ///////////////////////////////////////////////////////////////////////////////
@@ -646,22 +680,6 @@
 
 
 static void
-destroy_tunnel (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ServiceSession * session = cls;
-
-  if (session->tunnel)
-    {
-      GNUNET_MESH_tunnel_destroy (session->tunnel);
-      session->tunnel = NULL;
-    }
-  session->service_transmit_handle = NULL;
-  // we need to set this to NULL so there is no problem with double-cancel 
later on.
-}
-
-
-static void
 free_session (struct ServiceSession * session)
 {
   unsigned int i;
@@ -690,7 +708,6 @@
 //                      Event and Message Handlers
 ///////////////////////////////////////////////////////////////////////////////
 
-
 /**
  * A client disconnected. 
  * 
@@ -711,24 +728,24 @@
 
   // start from the tail, old stuff will be there...
   for (elem = from_client_head; NULL != elem; elem = next)
-    {
-      next = elem->next;
-      if (elem->client != client)
-        continue;
+  {
+    next = elem->next;
+    if (elem->client != client)
+      continue;
 
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Client (%p) disconnected from 
us.\n"), client);
-      GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, elem);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Client (%p) disconnected from 
us.\n"), client);
+    GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, elem);
 
-      if (!(elem->role == BOB && elem->state == FINALIZED))
-        {
-          //we MUST terminate any client message underway
-          if (elem->service_transmit_handle && elem->tunnel)
-            GNUNET_MESH_notify_transmit_ready_cancel 
(elem->service_transmit_handle);
-          if (elem->tunnel && elem->state == WAITING_FOR_RESPONSE_FROM_SERVICE)
-            destroy_tunnel (elem, NULL);
-        }
-      free_session (elem);
+    if (!(elem->role == BOB && elem->state == FINALIZED))
+    {
+      //we MUST terminate any client message underway
+      if (elem->service_transmit_handle && elem->tunnel)
+        GNUNET_MESH_notify_transmit_ready_cancel 
(elem->service_transmit_handle);
+      if (elem->tunnel && elem->state == WAITING_FOR_RESPONSE_FROM_SERVICE)
+        GNUNET_MESH_tunnel_destroy (elem->tunnel);
     }
+    free_session (elem);
+  }
 }
 
 
@@ -746,9 +763,13 @@
 prepare_client_end_notification (void * cls,
                                  const struct GNUNET_SCHEDULER_TaskContext * 
tc)
 {
-  struct ServiceSession * session = cls;
+  struct TaskClosure * task = cls;
+  struct ServiceSession * session = task->my_session;
   struct GNUNET_SCALARPRODUCT_client_response * msg;
   struct MessageObject * msg_obj;
+  
+  GNUNET_CONTAINER_DLL_remove (tasklist_head, tasklist_tail, task);
+  GNUNET_free(task);
 
   msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_client_response);
   msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT);
@@ -919,11 +940,14 @@
   //disconnect our client
   if ( ! request->service_transmit_handle)
     {
+      struct TaskClosure * task = GNUNET_new(struct TaskClosure);
+      
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response 
message via mesh!)\n"));
       GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
response);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                    &prepare_client_end_notification,
-                                    response);
+      task->my_session = response;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
       return GNUNET_NO;
     }
   return GNUNET_OK;
@@ -1156,7 +1180,8 @@
 prepare_service_request (void *cls,
                          const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct ServiceSession * session = cls;
+  struct TaskClosure * task = cls;
+  struct ServiceSession * session = task->my_session;
   unsigned char * current;
   struct GNUNET_SCALARPRODUCT_service_request * msg;
   struct MessageObject * msg_obj;
@@ -1166,8 +1191,10 @@
   size_t element_length = 0; //gets initialized by gcry_mpi_print, but the 
compiler doesn't know that
   gcry_mpi_t a;
   uint32_t value;
+  
+  GNUNET_CONTAINER_DLL_remove (tasklist_head, tasklist_tail, task);
+  GNUNET_free(task);
 
-  GNUNET_assert (NULL != cls);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new tunnel to 
peer (%s)!\n"), GNUNET_i2s (&session->peer));
 
   msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_request)
@@ -1180,12 +1207,15 @@
       + session->mask_length
       + my_pubkey_external_length)
     {
+      struct TaskClosure * task = GNUNET_new(struct TaskClosure);
       // TODO FEATURE: fallback to fragmentation, in case the message is too 
long
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, 
fragmentation is currently not supported!\n"));
       GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
session);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                    &prepare_client_end_notification,
-                                    session);
+      
+      task->my_session = session;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                    task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
       return;
     }
   msg = GNUNET_malloc (msg_length);
@@ -1261,13 +1291,16 @@
                                                                         
msg_obj);
   if ( ! session->service_transmit_handle)
     {
+      struct TaskClosure * task = GNUNET_new(struct TaskClosure);
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not send mutlicast message 
to tunnel!\n"));
       GNUNET_free (msg_obj);
       GNUNET_free (msg);
       GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
session);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                    &prepare_client_end_notification,
-                                    session);
+      
+      task->my_session = session;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                    task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
     }
 }
 
@@ -1287,6 +1320,7 @@
                        const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_SCALARPRODUCT_client_request * msg = (const struct 
GNUNET_SCALARPRODUCT_client_request *) message;
+  struct TaskClosure * task;
   struct ServiceSession * session;
   uint16_t element_count;
   uint16_t mask_length;
@@ -1399,7 +1433,12 @@
           return;
         }
       session->state = WAITING_FOR_BOBS_CONNECT;
-      GNUNET_SCHEDULER_add_now(&prepare_service_request, (void*) session);
+      
+      task = GNUNET_new(struct TaskClosure);
+      task->my_session = session;
+      task->my_handle = GNUNET_SCHEDULER_add_now (&prepare_service_request, 
task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
+      
       GNUNET_SERVER_receive_done (client, GNUNET_YES);
     }
   else
@@ -1428,7 +1467,11 @@
           if (GNUNET_OK != compute_service_response (requesting_session, 
session))
             {
               GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
session);
-              GNUNET_SCHEDULER_add_now(&prepare_client_end_notification, 
session);
+              
+              task = GNUNET_new(struct TaskClosure);
+              task->my_session = session;
+              task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification, task);
+              GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
             }
         }
       else
@@ -1483,6 +1526,7 @@
   struct ServiceSession * session = tunnel_ctx;
   struct ServiceSession * client_session;
   struct ServiceSession * curr;
+  struct TaskClosure * task;
   
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Peer disconnected, terminating 
session %s with peer (%s)\n"), GNUNET_h2s (&session->key), GNUNET_i2s 
(&session->peer));
   if (ALICE == session->role) {
@@ -1496,12 +1540,13 @@
           GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
session);
           break;
         }
-      // FIXME: dangling tasks, code duplication, use-after-free, fun...
-      GNUNET_SCHEDULER_add_now (&destroy_tunnel,
-                                session);
+      session->tunnel = NULL;
       // if this happened before we received the answer, we must terminate the 
session
-      GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
-                                session);
+      task = GNUNET_new(struct TaskClosure);
+      task->my_session = session;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
     }
   }
   else { //(BOB == session->role)
@@ -1528,8 +1573,12 @@
     {
       // remove the session, we just found it in the queue, so it must be there
       GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
client_session);
-      GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
-                                client_session);
+      
+      task = GNUNET_new(struct TaskClosure);
+      task->my_session = client_session;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
     }
   }
 }
@@ -1636,7 +1685,8 @@
 prepare_client_response (void *cls,
                          const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct ServiceSession * session = cls;
+  struct TaskClosure * task = cls;
+  struct ServiceSession * session = task->my_session;
   struct GNUNET_SCALARPRODUCT_client_response * msg;
   unsigned char * product_exported = NULL;
   size_t product_length = 0;
@@ -1644,6 +1694,9 @@
   struct MessageObject * msg_obj;
   int8_t range = 0;
   int sign;
+  
+  GNUNET_CONTAINER_DLL_remove (tasklist_head, tasklist_tail, task);
+  GNUNET_free(task);
 
   if (session->product)
     {
@@ -1888,11 +1941,13 @@
   // and notify our client-session that we could not complete the session
   if (responder_session)
     {
+      struct TaskClosure * task = GNUNET_new(struct TaskClosure);
       // we just found the responder session in this queue
       GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, 
responder_session);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                    &prepare_client_end_notification,
-                                    responder_session);
+      task->my_session = responder_session;
+      task->my_handle = GNUNET_SCHEDULER_add_now 
(&prepare_client_end_notification,
+                                task);
+      GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
     }
   return GNUNET_SYSERR;
 }
@@ -1919,6 +1974,7 @@
 
   struct ServiceSession * session;
   struct GNUNET_SCALARPRODUCT_service_response * msg = (struct 
GNUNET_SCALARPRODUCT_service_response *) message;
+  struct TaskClosure * task;
   unsigned char * current;
   uint16_t count;
   gcry_mpi_t s = NULL;
@@ -2025,11 +2081,14 @@
   // the tunnel has done its job, terminate our connection and the tunnel
   // the peer will be notified that the tunnel was destroyed via 
tunnel_destruction_handler
   GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
-  GNUNET_SCHEDULER_add_now (&destroy_tunnel, session); // FIXME: use after 
free!
   // send message with product to client
-  /* session->current_task = */ GNUNET_SCHEDULER_add_now 
(&prepare_client_response, session); // FIXME: dangling task!
-  return GNUNET_OK;
-  // if success: terminate the session gracefully, else terminate with error
+  
+  task = GNUNET_new(struct TaskClosure);
+  task->my_session = session;
+  task->my_handle = GNUNET_SCHEDULER_add_now (&prepare_client_response, task);
+  GNUNET_CONTAINER_DLL_insert (tasklist_head, tasklist_tail, task);
+  // just close the connection.
+  return GNUNET_SYSERR;
 }
 
 
@@ -2043,21 +2102,18 @@
 shutdown_task (void *cls,
                const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct ServiceSession * curr;
-  struct ServiceSession * next;
+  struct ServiceSession * session;
+  struct TaskClosure * task;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Shutting down, initiating 
cleanup.\n"));
 
   do_shutdown = GNUNET_YES;
+  for (task = tasklist_head; NULL != task; task = task->next)
+      GNUNET_SCHEDULER_cancel(task->my_handle);
+  
   // terminate all owned open tunnels.
-  for (curr = from_client_head; NULL != curr; curr = next)
-    {
-      next = curr->next;
-      if (FINALIZED != curr->state)
-        {
-          destroy_tunnel (curr, NULL);
-          curr->state = FINALIZED;
-        }
-    }
+  for (session = from_client_head; NULL != session; session = session->next)
+      if (FINALIZED != session->state)
+        GNUNET_MESH_tunnel_destroy (session->tunnel);
   if (my_mesh)
     {
       GNUNET_MESH_disconnect (my_mesh);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]