From dcec3f12b5b61d33fe333c4037cf0a34faa2b705 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 4 Feb 2020 16:29:48 +0100 Subject: [PATCH] remote-node: safely activate and deactivate a link Make sure we execute the admin of the target links in the data thread. --- src/modules/module-client-node/remote-node.c | 42 +++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index cb5ce75c5..0cf9cae6b 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -61,13 +61,6 @@ struct mix { bool active; }; -struct link { - uint32_t node_id; - struct pw_memmap *map; - struct pw_node_target target; - int signalfd; -}; - struct node_data { struct pw_context *context; @@ -98,6 +91,14 @@ struct node_data { struct pw_array links; }; +struct link { + struct node_data *data; + struct pw_memmap *map; + struct pw_node_target target; + uint32_t node_id; + int signalfd; +}; + /** \endcond */ static struct link *find_activation(struct pw_array *links, uint32_t node_id) @@ -111,13 +112,23 @@ static struct link *find_activation(struct pw_array *links, uint32_t node_id) return NULL; } +static int +do_deactivate_link(struct spa_loop *loop, + bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct link *link = user_data; + spa_list_remove(&link->target.link); + return 0; +} + static void clear_link(struct node_data *data, struct link *link) { + pw_loop_invoke(data->context->data_loop, + do_deactivate_link, SPA_ID_INVALID, NULL, 0, true, link); link->node_id = SPA_ID_INVALID; link->target.activation = NULL; pw_memmap_free(link->map); close(link->signalfd); - spa_list_remove(&link->target.link); } static void clean_transport(struct node_data *data) @@ -798,6 +809,16 @@ static int link_signal_func(void *user_data) return 0; } +static int +do_activate_link(struct spa_loop *loop, + bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct link *link = user_data; + struct node_data *d = link->data; + spa_list_append(&d->node->rt.target_list, &link->target.link); + return 0; +} + static int client_node_set_activation(void *object, uint32_t node_id, @@ -843,6 +864,7 @@ client_node_set_activation(void *object, res = -errno; goto error_exit; } + link->data = data; link->node_id = node_id; link->map = mm; link->target.activation = ptr; @@ -850,7 +872,9 @@ client_node_set_activation(void *object, link->target.signal = link_signal_func; link->target.data = link; link->target.node = NULL; - spa_list_append(&node->rt.target_list, &link->target.link); + + pw_loop_invoke(data->context->data_loop, + do_activate_link, SPA_ID_INVALID, NULL, 0, false, link); pw_log_debug("node %p: link %p: fd:%d id:%u state %p required %d, pending %d", node, link, signalfd,