diff options
author | Maria Matejka <mq@ucw.cz> | 2021-12-07 12:47:42 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-12-07 13:05:20 +0100 |
commit | a9efce68b59efa1d2ceb89a2c19f9e2bf50391ea (patch) | |
tree | 726a52b628419f63d904d2d8e7457980e22b9ef6 | |
parent | 4f43d326b4ab8c8ddd4bc00152859e768c27590a (diff) |
Fixed a race condition in channel aux table cleanup
-rw-r--r-- | nest/proto.c | 40 | ||||
-rw-r--r-- | nest/protocol.h | 1 |
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; }; /* |