diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-09-26 14:50:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-09-26 14:50:19 +0000 |
commit | ea5dba2343416eb8f049eb55accf05b6b56d8d10 (patch) | |
tree | 33f4ce1890e57e8bf1bec80f3ccd8c7d00d509ff /src/util | |
parent | affce940110bff113f6c204d5327b4c3df9b1749 (diff) | |
download | gnunet-ea5dba2343416eb8f049eb55accf05b6b56d8d10.tar.gz gnunet-ea5dba2343416eb8f049eb55accf05b6b56d8d10.zip |
fix #4680
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/service_new.c | 69 |
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 | */ |
1956 | static int | 1962 | static int |
1957 | service_client_mst_cb (void *cls, | 1963 | service_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 | */ | ||
2331 | static void | ||
2332 | finish_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 | ||