diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-02-26 20:26:31 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-02-26 20:26:40 +0100 |
commit | fc44a16d5a5761fcc14c1de29daa3451be251edd (patch) | |
tree | 1b62e0fad489b08d06786c3a20f30ae518343a8f /src | |
parent | a5ed93ab801ed92f77d1dffd566dff56ac3d6e2e (diff) | |
download | gnunet-fc44a16d5a5761fcc14c1de29daa3451be251edd.tar.gz gnunet-fc44a16d5a5761fcc14c1de29daa3451be251edd.zip |
move path destruction to separate task to avoid deep-recursion free-while-in-use issue
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_peer.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c index 7b944afd8..350c8efae 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ b/src/cadet/gnunet-service-cadet-new_peer.c | |||
@@ -157,9 +157,9 @@ struct CadetPeer | |||
157 | struct GCD_search_handle *search_h; | 157 | struct GCD_search_handle *search_h; |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * Task to stop the DHT search for paths to this peer | 160 | * Task to clean up @e path_heap asynchronously. |
161 | */ | 161 | */ |
162 | struct GNUNET_SCHEDULER_Task *search_delayedXXX; | 162 | struct GNUNET_SCHEDULER_Task *heap_cleanup_task; |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * Task to destroy this entry. | 165 | * Task to destroy this entry. |
@@ -361,6 +361,11 @@ destroy_peer (void *cls) | |||
361 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | 361 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); |
362 | cp->path_heap = NULL; | 362 | cp->path_heap = NULL; |
363 | } | 363 | } |
364 | if (NULL != cp->heap_cleanup_task) | ||
365 | { | ||
366 | GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task); | ||
367 | cp->heap_cleanup_task = NULL; | ||
368 | } | ||
364 | GNUNET_free_non_null (cp->hello); | 369 | GNUNET_free_non_null (cp->hello); |
365 | /* Peer should not be freed if paths exist; if there are no paths, | 370 | /* Peer should not be freed if paths exist; if there are no paths, |
366 | there ought to be no connections, and without connections, no | 371 | there ought to be no connections, and without connections, no |
@@ -892,6 +897,41 @@ GCP_path_entry_remove (struct CadetPeer *cp, | |||
892 | 897 | ||
893 | 898 | ||
894 | /** | 899 | /** |
900 | * Prune down the number of paths to this peer, we seem to | ||
901 | * have way too many. | ||
902 | * | ||
903 | * @param cls the `struct CadetPeer` to maintain the path heap for | ||
904 | */ | ||
905 | static void | ||
906 | path_heap_cleanup (void *cls) | ||
907 | { | ||
908 | struct CadetPeer *cp = cls; | ||
909 | struct CadetPeerPath *root; | ||
910 | |||
911 | cp->heap_cleanup_task = NULL; | ||
912 | while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
913 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
914 | { | ||
915 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
916 | (Note that this intentionally keeps highly desireable, but currently | ||
917 | unused paths around in the hope that we might be able to switch, even | ||
918 | if the number of paths exceeds the threshold.) */ | ||
919 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
920 | if (NULL != | ||
921 | GCPP_get_connection (root, | ||
922 | cp, | ||
923 | GCPP_get_length (root) - 1)) | ||
924 | break; /* can't fix */ | ||
925 | /* Got plenty of paths to this destination, and this is a low-quality | ||
926 | one that we don't care about. Allow it to die. */ | ||
927 | GNUNET_assert (root == | ||
928 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
929 | GCPP_release (root); | ||
930 | } | ||
931 | } | ||
932 | |||
933 | |||
934 | /** | ||
895 | * Try adding a @a path to this @a peer. If the peer already | 935 | * Try adding a @a path to this @a peer. If the peer already |
896 | * has plenty of paths, return NULL. | 936 | * has plenty of paths, return NULL. |
897 | * | 937 | * |
@@ -958,27 +998,11 @@ GCP_attach_path (struct CadetPeer *cp, | |||
958 | desirability); | 998 | desirability); |
959 | 999 | ||
960 | /* Consider maybe dropping other paths because of the new one */ | 1000 | /* Consider maybe dropping other paths because of the new one */ |
961 | if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | 1001 | if ( (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= |
962 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | 1002 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) && |
963 | { | 1003 | (NULL != cp->heap_cleanup_task) ) |
964 | /* Now we have way too many, drop least desirable UNLESS it is in use! | 1004 | cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup, |
965 | (Note that this intentionally keeps highly desireable, but currently | 1005 | cp); |
966 | unused paths around in the hope that we might be able to switch, even | ||
967 | if the number of paths exceeds the threshold.) */ | ||
968 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
969 | if ( (path != root) && | ||
970 | (NULL == | ||
971 | GCPP_get_connection (root, | ||
972 | cp, | ||
973 | GCPP_get_length (root) - 1)) ) | ||
974 | { | ||
975 | /* Got plenty of paths to this destination, and this is a low-quality | ||
976 | one that we don't care about. Allow it to die. */ | ||
977 | GNUNET_assert (root == | ||
978 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
979 | GCPP_release (root); | ||
980 | } | ||
981 | } | ||
982 | return hn; | 1006 | return hn; |
983 | } | 1007 | } |
984 | 1008 | ||