gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r38019 - gnunet/src/util


From: gnunet
Subject: [GNUnet-SVN] r38019 - gnunet/src/util
Date: Mon, 26 Sep 2016 16:50:20 +0200

Author: grothoff
Date: 2016-09-26 16:50:19 +0200 (Mon, 26 Sep 2016)
New Revision: 38019

Modified:
   gnunet/src/util/service_new.c
Log:
fix #4680

Modified: gnunet/src/util/service_new.c
===================================================================
--- gnunet/src/util/service_new.c       2016-09-26 14:33:57 UTC (rev 38018)
+++ gnunet/src/util/service_new.c       2016-09-26 14:50:19 UTC (rev 38019)
@@ -255,6 +255,12 @@
   struct GNUNET_SCHEDULER_Task *warn_task;
 
   /**
+   * Task run to finish dropping the client after the stack has
+   * properly unwound.
+   */
+  struct GNUNET_SCHEDULER_Task *drop_task;
+
+  /**
    * Task that receives data from the client to
    * pass it to the handlers.
    */
@@ -1951,7 +1957,7 @@
  *
  * @param cls closure with the `struct GNUNET_SERVICE_Client *`
  * @param message the actual message
- * @return #GNUNET_OK on success (always)
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the client was dropped
  */
 static int
 service_client_mst_cb (void *cls,
@@ -1970,6 +1976,8 @@
                                    client);
   GNUNET_MQ_inject_message (client->mq,
                             message);
+  if (NULL != client->drop_task)
+    return GNUNET_SYSERR;
   return GNUNET_OK;
 }
 
@@ -1994,8 +2002,11 @@
   if (GNUNET_SYSERR == ret)
   {
     /* client closed connection (or IO error) */
-    GNUNET_assert (GNUNET_NO == client->needs_continue);
-    GNUNET_SERVICE_client_drop (client);
+    if (NULL == client->drop_task)
+    {
+      GNUNET_assert (GNUNET_NO == client->needs_continue);
+      GNUNET_SERVICE_client_drop (client);
+    }
     return;
   }
   if (GNUNET_NO == ret)
@@ -2313,6 +2324,35 @@
 
 
 /**
+ * Asynchronously finish dropping the client.
+ *
+ * @param cls the `struct GNUNET_SERVICE_Client`.
+ */
+static void
+finish_client_drop (void *cls)
+{
+  struct GNUNET_SERVICE_Client *c = cls;
+  struct GNUNET_SERVICE_Handle *sh = c->sh;
+
+  GNUNET_MST_destroy (c->mst);
+  GNUNET_MQ_destroy (c->mq);
+  if (GNUNET_NO == c->persist)
+  {
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_NETWORK_socket_close (c->sock));
+  }
+  else
+  {
+    GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
+  }
+  GNUNET_free (c);
+  if ( (GNUNET_YES == sh->got_shutdown) &&
+       (GNUNET_NO == have_non_monitor_clients (sh)) )
+    GNUNET_SERVICE_shutdown (sh);
+}
+
+
+/**
  * Ask the server to disconnect from the given client.  This is the
  * same as returning #GNUNET_SYSERR within the check procedure when
  * handling a message, wexcept that it allows dropping of a client even
@@ -2327,6 +2367,12 @@
 {
   struct GNUNET_SERVICE_Handle *sh = c->sh;
 
+  if (NULL != c->drop_task)
+  {
+    /* asked to drop twice! */
+    GNUNET_break (0);
+    return;
+  }
   GNUNET_CONTAINER_DLL_remove (sh->clients_head,
                                sh->clients_tail,
                                c);
@@ -2348,21 +2394,8 @@
     GNUNET_SCHEDULER_cancel (c->send_task);
     c->send_task = NULL;
   }
-  GNUNET_MST_destroy (c->mst);
-  GNUNET_MQ_destroy (c->mq);
-  if (GNUNET_NO == c->persist)
-  {
-    GNUNET_break (GNUNET_OK ==
-                 GNUNET_NETWORK_socket_close (c->sock));
-  }
-  else
-  {
-    GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
-  }
-  GNUNET_free (c);
-  if ( (GNUNET_YES == sh->got_shutdown) &&
-       (GNUNET_NO == have_non_monitor_clients (sh)) )
-    GNUNET_SERVICE_shutdown (sh);
+  c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop,
+                                           c);
 }
 
 




reply via email to

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