summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-12-07 12:47:42 +0100
committerMaria Matejka <mq@ucw.cz>2021-12-07 13:05:20 +0100
commita9efce68b59efa1d2ceb89a2c19f9e2bf50391ea (patch)
tree726a52b628419f63d904d2d8e7457980e22b9ef6
parent4f43d326b4ab8c8ddd4bc00152859e768c27590a (diff)
Fixed a race condition in channel aux table cleanup
-rw-r--r--nest/proto.c40
-rw-r--r--nest/protocol.h1
2 files changed, 33 insertions, 8 deletions
diff --git a/nest/proto.c b/nest/proto.c
index a18d9332..341581ab 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -667,9 +667,14 @@ static void
channel_aux_stopped(void *data)
{
struct channel_aux_table *cat;
+
RT_LOCKED((rtable *) data, t)
cat = t->config->owner;
+ ASSERT_DIE(cat->push.hook == NULL);
+ ASSERT_DIE(cat->get.hook == NULL);
+ ASSERT_DIE(cat->stop_pending);
+
struct channel *c = cat->c;
if (channel_aux_imex(cat))
@@ -685,7 +690,15 @@ static void
channel_aux_import_stopped(void *_cat)
{
struct channel_aux_table *cat = _cat;
+
cat->push.hook = NULL;
+
+ if (!cat->get.hook)
+ RT_LOCKED(cat->tab, t)
+ {
+ t->delete = channel_aux_stopped;
+ rt_unlock_table(t);
+ }
}
static void
@@ -694,23 +707,31 @@ channel_aux_export_stopped(struct rt_export_request *req)
struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, get, req);
req->hook = NULL;
- int del;
- RT_LOCKED(cat->tab, t)
- del = !!t->delete;
+ if (cat->refeed_pending && !cat->stop_pending)
+ {
+ cat->refeed_pending = 0;
+ rt_request_export(cat->tab, req);
- if (del)
return;
+ }
- ASSERT_DIE(cat->refeed_pending);
- cat->refeed_pending = 0;
- rt_request_export(cat->tab, req);
+ if (!cat->push.hook)
+ RT_LOCKED(cat->tab, t)
+ {
+ t->delete = channel_aux_stopped;
+ rt_unlock_table(t);
+ }
}
static void
channel_aux_stop(struct channel_aux_table *cat)
{
+ ASSERT_DIE(!cat->stop_pending);
+
+ cat->stop_pending = 1;
+
RT_LOCKED(cat->tab, t)
- t->delete = channel_aux_stopped;
+ rt_lock_table(t);
cat->push_stopped = (event) {
.hook = channel_aux_import_stopped,
@@ -966,6 +987,9 @@ channel_setup_out_table(struct channel *c)
static void
channel_aux_request_refeed(struct channel_aux_table *cat)
{
+ if (cat->stop_pending)
+ return;
+
cat->refeed_pending = 1;
rt_stop_export(&cat->get, channel_aux_export_stopped);
}
diff --git a/nest/protocol.h b/nest/protocol.h
index 1d4f2059..f07bb4df 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -572,6 +572,7 @@ struct channel_aux_table {
rtable *tab;
event *stop;
u8 refeed_pending;
+ u8 stop_pending;
};
/*