remote-node: safely activate and deactivate a link

Make sure we execute the admin of the target links in the data
thread.
This commit is contained in:
Wim Taymans 2020-02-04 16:29:48 +01:00
parent 8abbf653e6
commit dcec3f12b5

View file

@ -61,13 +61,6 @@ struct mix {
bool active; bool active;
}; };
struct link {
uint32_t node_id;
struct pw_memmap *map;
struct pw_node_target target;
int signalfd;
};
struct node_data { struct node_data {
struct pw_context *context; struct pw_context *context;
@ -98,6 +91,14 @@ struct node_data {
struct pw_array links; 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 */ /** \endcond */
static struct link *find_activation(struct pw_array *links, uint32_t node_id) 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; 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) 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->node_id = SPA_ID_INVALID;
link->target.activation = NULL; link->target.activation = NULL;
pw_memmap_free(link->map); pw_memmap_free(link->map);
close(link->signalfd); close(link->signalfd);
spa_list_remove(&link->target.link);
} }
static void clean_transport(struct node_data *data) static void clean_transport(struct node_data *data)
@ -798,6 +809,16 @@ static int link_signal_func(void *user_data)
return 0; 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 static int
client_node_set_activation(void *object, client_node_set_activation(void *object,
uint32_t node_id, uint32_t node_id,
@ -843,6 +864,7 @@ client_node_set_activation(void *object,
res = -errno; res = -errno;
goto error_exit; goto error_exit;
} }
link->data = data;
link->node_id = node_id; link->node_id = node_id;
link->map = mm; link->map = mm;
link->target.activation = ptr; link->target.activation = ptr;
@ -850,7 +872,9 @@ client_node_set_activation(void *object,
link->target.signal = link_signal_func; link->target.signal = link_signal_func;
link->target.data = link; link->target.data = link;
link->target.node = NULL; 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", pw_log_debug("node %p: link %p: fd:%d id:%u state %p required %d, pending %d",
node, link, signalfd, node, link, signalfd,