summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Bünger <buenger@mytum.de>2018-08-13 17:32:58 +0200
committerJulius Bünger <buenger@mytum.de>2018-08-13 17:32:58 +0200
commit3318097204119e550a5e9691d7c3f11ea64fc8a8 (patch)
tree088a753f3a98a875e5f8e55dece8d57aaeef9fca
parent32a0ea5a355f8ce1166376b9cb9b2d023f082400 (diff)
Schedule destruction of channel during destruction of other channel
-rw-r--r--src/rps/gnunet-service-rps.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index 18b9b792b..e0301af6b 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -275,6 +275,13 @@ struct ChannelCtx
* @brief The peer context associated with the channel
*/
struct PeerContext *peer_ctx;
+
+ /**
+ * @brief When channel destruction needs to be delayed (because it is called
+ * from within the cadet routine of another channel destruction) this task
+ * refers to the respective _SCHEDULER_Task.
+ */
+ struct GNUNET_SCHEDULER_Task *destruction_task;
};
/**
@@ -304,7 +311,6 @@ static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
static struct GNUNET_CADET_Handle *cadet_handle;
-
/**
* @brief Get the #PeerContext associated with a peer
*
@@ -864,13 +870,47 @@ destroy_channel (struct ChannelCtx *channel_ctx)
{
struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
- GNUNET_assert (channel_ctx == peer_ctx->send_channel_ctx ||
- channel_ctx == peer_ctx->recv_channel_ctx);
-
+ if (NULL != channel_ctx->destruction_task)
+ {
+ GNUNET_SCHEDULER_cancel (channel_ctx->destruction_task);
+ channel_ctx->destruction_task = NULL;
+ }
GNUNET_CADET_channel_destroy (channel_ctx->channel);
+ channel_ctx->channel = NULL;
remove_channel_ctx (channel_ctx);
}
+/**
+ * @brief Destroy a cadet channel.
+ *
+ * This satisfies the function signature of #GNUNET_SCHEDULER_TaskCallback.
+ *
+ * @param cls
+ */
+static void
+destroy_channel_cb (void *cls)
+{
+ struct ChannelCtx *channel_ctx = cls;
+ channel_ctx->destruction_task = NULL;
+ destroy_channel (channel_ctx);
+}
+
+/**
+ * @brief Schedule the destruction of a channel for immediately afterwards.
+ *
+ * In case a channel is to be destroyed from within the callback to the
+ * destruction of another channel (send channel), we cannot call
+ * GNUNET_CADET_channel_destroy directly, but need to use this scheduling
+ * construction.
+ *
+ * @param channel_ctx channel to be destroyed.
+ */
+static void
+schedule_channel_destruction (struct ChannelCtx *channel_ctx)
+{
+ channel_ctx->destruction_task =
+ GNUNET_SCHEDULER_add_now (destroy_channel_cb, channel_ctx);
+}
/**
* @brief Remove peer
@@ -937,11 +977,13 @@ destroy_peer (struct PeerContext *peer_ctx)
if (NULL != peer_ctx->send_channel_ctx)
{
- destroy_channel (peer_ctx->send_channel_ctx);
+ /* This is possibly called from within channel destruction */
+ schedule_channel_destruction (peer_ctx->send_channel_ctx);
}
if (NULL != peer_ctx->recv_channel_ctx)
{
- destroy_channel (peer_ctx->recv_channel_ctx);
+ /* This is possibly called from within channel destruction */
+ schedule_channel_destruction (peer_ctx->recv_channel_ctx);
}
if (GNUNET_YES !=
@@ -3874,6 +3916,7 @@ shutdown_task (void *cls)
RPS_sampler_destroy (client_sampler);
GNUNET_CADET_close_port (cadet_port);
GNUNET_CADET_disconnect (cadet_handle);
+ cadet_handle = NULL;
View_destroy ();
CustomPeerMap_destroy (push_map);
CustomPeerMap_destroy (pull_map);