From f74bc79fcea9c0ecb5dc0af8e49764fd31e34d4d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Jan 2017 16:33:01 +0100 Subject: [PATCH] fix shutdown logic --- src/cadet/gnunet-service-cadet-new.c | 24 +++++++++++ src/cadet/gnunet-service-cadet-new_core.c | 3 +- src/cadet/gnunet-service-cadet-new_paths.c | 15 +------ src/cadet/gnunet-service-cadet-new_peer.c | 43 +++++++++++++++++--- src/cadet/gnunet-service-cadet-new_peer.h | 10 +++++ src/cadet/gnunet-service-cadet-new_tunnels.c | 6 ++- 6 files changed, 80 insertions(+), 21 deletions(-) diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c index b0d8fc32d..2e431c034 100644 --- a/src/cadet/gnunet-service-cadet-new.c +++ b/src/cadet/gnunet-service-cadet-new.c @@ -334,6 +334,27 @@ destroy_tunnels_now (void *cls, } +/** + * Callback invoked on all peers to destroy all tunnels + * that may still exist. + * + * @param cls NULL + * @param pid identify of a peer + * @param value a `struct CadetPeer` that may still have a tunnel + * @return #GNUNET_OK (iterate over all entries) + */ +static int +destroy_paths_now (void *cls, + const struct GNUNET_PeerIdentity *pid, + void *value) +{ + struct CadetPeer *cp = value; + + GCP_drop_owned_paths (cp); + return GNUNET_OK; +} + + /** * Task run during shutdown. * @@ -366,6 +387,9 @@ shutdown_task (void *cls) GCP_iterate_all (&destroy_tunnels_now, NULL); /* All tunnels, channels, connections and CORE must be down before this point. */ + GCP_iterate_all (&destroy_paths_now, + NULL); + /* All paths, tunnels, channels, connections and CORE must be down before this point. */ GCP_destroy_all_peers (); if (NULL != peers) { diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet-new_core.c index 7cff68f4a..1e35a5102 100644 --- a/src/cadet/gnunet-service-cadet-new_core.c +++ b/src/cadet/gnunet-service-cadet-new_core.c @@ -476,7 +476,8 @@ handle_connection_create (void *cls, GNUNET_sh2s (&msg->cid.connection_of_tunnel)); path = GCPP_get_path_from_route (path_length - 1, pids); - GCT_add_inbound_connection (GCT_create_tunnel (origin), + GCT_add_inbound_connection (GCP_get_tunnel (origin, + GNUNET_YES), &msg->cid, path); return; diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet-new_paths.c index d0df2a1f4..39658d4e8 100644 --- a/src/cadet/gnunet-service-cadet-new_paths.c +++ b/src/cadet/gnunet-service-cadet-new_paths.c @@ -54,13 +54,6 @@ struct CadetPeerPath */ struct GNUNET_CONTAINER_HeapNode *hn; - /** - * Connections using this path, by destination peer - * (each hop of the path could correspond to an - * active connection). - */ - struct GNUNET_CONTAINER_MultiPeerMap *connections; - /** * Desirability of the path. How unique is it for the various peers * on it? @@ -185,9 +178,6 @@ path_destroy (struct CadetPeerPath *path) LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying path %s\n", GCPP_2s (path)); - GNUNET_assert (0 == - GNUNET_CONTAINER_multipeermap_size (path->connections)); - GNUNET_CONTAINER_multipeermap_destroy (path->connections); for (unsigned int i=0;ientries_length;i++) GNUNET_free (path->entries[i]); GNUNET_free (path->entries); @@ -214,10 +204,7 @@ GCPP_release (struct CadetPeerPath *path) entry = path->entries[path->entries_length - 1]; while (1) { - /* cut 'off' end of path, verifying it is not in use */ - GNUNET_assert (NULL == - GNUNET_CONTAINER_multipeermap_get (path->connections, - GCP_get_id (entry->peer))); + /* cut 'off' end of path */ GCP_path_entry_remove (entry->peer, entry, path->entries_length - 1); diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c index fa1cc9ed9..1505914a1 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ b/src/cadet/gnunet-service-cadet-new_peer.c @@ -40,7 +40,6 @@ #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "cadet_protocol.h" -#include "cadet_path.h" #include "gnunet-service-cadet-new.h" #include "gnunet-service-cadet-new_connection.h" #include "gnunet-service-cadet-new_dht.h" @@ -257,7 +256,8 @@ destroy_peer (void *cls) cp->destroy_task = NULL; GNUNET_assert (NULL == cp->t); GNUNET_assert (NULL == cp->core_mq); - GNUNET_assert (0 == cp->path_dll_length); + for (unsigned int i=0;ipath_dll_length;i++) + GNUNET_assert (NULL == cp->path_heads[i]); GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (peers, @@ -284,7 +284,11 @@ destroy_peer (void *cls) cp->connectivity_suggestion = NULL; } GNUNET_CONTAINER_multishortmap_destroy (cp->connections); - GNUNET_CONTAINER_heap_destroy (cp->path_heap); + if (NULL != cp->path_heap) + { + GNUNET_CONTAINER_heap_destroy (cp->path_heap); + cp->path_heap = NULL; + } GNUNET_free_non_null (cp->hello); /* Peer should not be freed if paths exist; if there are no paths, there ought to be no connections, and without connections, no @@ -418,8 +422,9 @@ consider_peer_destroy (struct CadetPeer *cp) cp); return; } - if (0 < cp->path_dll_length) - return; /* still relevant! */ + for (unsigned int i=0;ipath_dll_length;i++) + if (NULL != cp->path_heads[i]) + return; /* still relevant! */ if (NULL != cp->hello) { /* relevant only until HELLO expires */ @@ -627,6 +632,28 @@ GCP_destroy_all_peers () } +/** + * Drop all paths owned by this peer, and do not + * allow new ones to be added: We are shutting down. + * + * @param cp peer to drop paths to + */ +void +GCP_drop_owned_paths (struct CadetPeer *cp) +{ + struct CadetPeerPath *path; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Destroying all paths to %s\n", + GCP_2s (cp)); + while (NULL != (path = + GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) + GCPP_release (path); + GNUNET_CONTAINER_heap_destroy (cp->path_heap); + cp->path_heap = NULL; +} + + /** * Add an entry to the DLL of all of the paths that this peer is on. * @@ -730,6 +757,12 @@ GCP_attach_path (struct CadetPeer *cp, GNUNET_CONTAINER_HeapCostType root_desirability; struct GNUNET_CONTAINER_HeapNode *hn; + if (NULL == cp->path_heap) + { + /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ + GNUNET_assert (GNUNET_NO == force); + return NULL; + } desirability = GCPP_get_desirability (path); if (GNUNET_NO == force) { diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h index 8a1d3ed5c..aaaef15b8 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.h +++ b/src/cadet/gnunet-service-cadet-new_peer.h @@ -90,6 +90,16 @@ unsigned int GCP_count_paths (const struct CadetPeer *cp); +/** + * Drop all paths owned by this peer, and do not + * allow new ones to be added: We are shutting down. + * + * @param cp peer to drop paths to + */ +void +GCP_drop_owned_paths (struct CadetPeer *cp); + + /** * Peer path iterator. * diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c index 1afa451ec..a1a7b80fd 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.c +++ b/src/cadet/gnunet-service-cadet-new_tunnels.c @@ -1601,7 +1601,11 @@ GCT_destroy_tunnel_now (struct CadetTunnel *t) { GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (t->channels)); - GNUNET_SCHEDULER_cancel (t->destroy_task); + if (NULL != t->destroy_task) + { + GNUNET_SCHEDULER_cancel (t->destroy_task); + t->destroy_task = NULL; + } destroy_tunnel (t); } -- 2.25.1