aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-26 14:50:19 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-26 14:50:19 +0000
commitea5dba2343416eb8f049eb55accf05b6b56d8d10 (patch)
tree33f4ce1890e57e8bf1bec80f3ccd8c7d00d509ff /src/util
parentaffce940110bff113f6c204d5327b4c3df9b1749 (diff)
downloadgnunet-ea5dba2343416eb8f049eb55accf05b6b56d8d10.tar.gz
gnunet-ea5dba2343416eb8f049eb55accf05b6b56d8d10.zip
fix #4680
Diffstat (limited to 'src/util')
-rw-r--r--src/util/service_new.c69
1 files changed, 51 insertions, 18 deletions
diff --git a/src/util/service_new.c b/src/util/service_new.c
index c547e3bf3..0b9e8fd82 100644
--- a/src/util/service_new.c
+++ b/src/util/service_new.c
@@ -255,6 +255,12 @@ struct GNUNET_SERVICE_Client
255 struct GNUNET_SCHEDULER_Task *warn_task; 255 struct GNUNET_SCHEDULER_Task *warn_task;
256 256
257 /** 257 /**
258 * Task run to finish dropping the client after the stack has
259 * properly unwound.
260 */
261 struct GNUNET_SCHEDULER_Task *drop_task;
262
263 /**
258 * Task that receives data from the client to 264 * Task that receives data from the client to
259 * pass it to the handlers. 265 * pass it to the handlers.
260 */ 266 */
@@ -1951,7 +1957,7 @@ warn_no_client_continue (void *cls)
1951 * 1957 *
1952 * @param cls closure with the `struct GNUNET_SERVICE_Client *` 1958 * @param cls closure with the `struct GNUNET_SERVICE_Client *`
1953 * @param message the actual message 1959 * @param message the actual message
1954 * @return #GNUNET_OK on success (always) 1960 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the client was dropped
1955 */ 1961 */
1956static int 1962static int
1957service_client_mst_cb (void *cls, 1963service_client_mst_cb (void *cls,
@@ -1970,6 +1976,8 @@ service_client_mst_cb (void *cls,
1970 client); 1976 client);
1971 GNUNET_MQ_inject_message (client->mq, 1977 GNUNET_MQ_inject_message (client->mq,
1972 message); 1978 message);
1979 if (NULL != client->drop_task)
1980 return GNUNET_SYSERR;
1973 return GNUNET_OK; 1981 return GNUNET_OK;
1974} 1982}
1975 1983
@@ -1994,8 +2002,11 @@ service_client_recv (void *cls)
1994 if (GNUNET_SYSERR == ret) 2002 if (GNUNET_SYSERR == ret)
1995 { 2003 {
1996 /* client closed connection (or IO error) */ 2004 /* client closed connection (or IO error) */
1997 GNUNET_assert (GNUNET_NO == client->needs_continue); 2005 if (NULL == client->drop_task)
1998 GNUNET_SERVICE_client_drop (client); 2006 {
2007 GNUNET_assert (GNUNET_NO == client->needs_continue);
2008 GNUNET_SERVICE_client_drop (client);
2009 }
1999 return; 2010 return;
2000 } 2011 }
2001 if (GNUNET_NO == ret) 2012 if (GNUNET_NO == ret)
@@ -2313,6 +2324,35 @@ GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
2313 2324
2314 2325
2315/** 2326/**
2327 * Asynchronously finish dropping the client.
2328 *
2329 * @param cls the `struct GNUNET_SERVICE_Client`.
2330 */
2331static void
2332finish_client_drop (void *cls)
2333{
2334 struct GNUNET_SERVICE_Client *c = cls;
2335 struct GNUNET_SERVICE_Handle *sh = c->sh;
2336
2337 GNUNET_MST_destroy (c->mst);
2338 GNUNET_MQ_destroy (c->mq);
2339 if (GNUNET_NO == c->persist)
2340 {
2341 GNUNET_break (GNUNET_OK ==
2342 GNUNET_NETWORK_socket_close (c->sock));
2343 }
2344 else
2345 {
2346 GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2347 }
2348 GNUNET_free (c);
2349 if ( (GNUNET_YES == sh->got_shutdown) &&
2350 (GNUNET_NO == have_non_monitor_clients (sh)) )
2351 GNUNET_SERVICE_shutdown (sh);
2352}
2353
2354
2355/**
2316 * Ask the server to disconnect from the given client. This is the 2356 * Ask the server to disconnect from the given client. This is the
2317 * same as returning #GNUNET_SYSERR within the check procedure when 2357 * same as returning #GNUNET_SYSERR within the check procedure when
2318 * handling a message, wexcept that it allows dropping of a client even 2358 * handling a message, wexcept that it allows dropping of a client even
@@ -2327,6 +2367,12 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2327{ 2367{
2328 struct GNUNET_SERVICE_Handle *sh = c->sh; 2368 struct GNUNET_SERVICE_Handle *sh = c->sh;
2329 2369
2370 if (NULL != c->drop_task)
2371 {
2372 /* asked to drop twice! */
2373 GNUNET_break (0);
2374 return;
2375 }
2330 GNUNET_CONTAINER_DLL_remove (sh->clients_head, 2376 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2331 sh->clients_tail, 2377 sh->clients_tail,
2332 c); 2378 c);
@@ -2348,21 +2394,8 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2348 GNUNET_SCHEDULER_cancel (c->send_task); 2394 GNUNET_SCHEDULER_cancel (c->send_task);
2349 c->send_task = NULL; 2395 c->send_task = NULL;
2350 } 2396 }
2351 GNUNET_MST_destroy (c->mst); 2397 c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop,
2352 GNUNET_MQ_destroy (c->mq); 2398 c);
2353 if (GNUNET_NO == c->persist)
2354 {
2355 GNUNET_break (GNUNET_OK ==
2356 GNUNET_NETWORK_socket_close (c->sock));
2357 }
2358 else
2359 {
2360 GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2361 }
2362 GNUNET_free (c);
2363 if ( (GNUNET_YES == sh->got_shutdown) &&
2364 (GNUNET_NO == have_non_monitor_clients (sh)) )
2365 GNUNET_SERVICE_shutdown (sh);
2366} 2399}
2367 2400
2368 2401