From 1196429c099a22944862938d8850a35d30550e03 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 3 Feb 2024 12:20:21 +0200 Subject: [PATCH] client-node: handle releasing mix for destroyed port The remote end may destroy the port via client_node_port_update(), before corresponding pw_impl_port_mix are released. clear_port() removes all struct mix, but this prevents the pw_impl_port_mix from being removed from io_map, which causes stale mix ids be left in io_map, so we end up continuously allocating new io areas. Make lifecycle of io_map entries match port_init_mix/release_mix exactly, separately from the lifecycle of the port and struct mix. When freeing struct mix in port_release_mix(), make sure it corresponds to the mix being released. --- src/modules/module-client-node/client-node.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index c493e24c9..ab019d36e 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -53,6 +53,7 @@ struct mix { struct port *port; uint32_t peer_id; uint32_t n_buffers; + uint32_t impl_mix_id; struct buffer buffers[MAX_BUFFERS]; }; @@ -228,6 +229,7 @@ static struct mix *create_mix(struct port *p, uint32_t mix_id) mix->mix_id = mix_id; mix->port = p; mix->n_buffers = 0; + mix->impl_mix_id = SPA_ID_INVALID; return mix; fail: @@ -1437,6 +1439,7 @@ static int port_init_mix(void *data, struct pw_impl_port_mix *mix) *mix->io = SPA_IO_BUFFERS_INIT; m->peer_id = mix->peer_id; + m->impl_mix_id = mix->id; if (impl->resource && impl->resource->version >= 4) pw_client_node_resource_port_set_mix_info(impl->resource, @@ -1462,7 +1465,7 @@ static int port_release_mix(void *data, struct pw_impl_port_mix *mix) pw_log_debug("%p: remove mix id:%d io:%p", impl, mix->id, mix->io); - if ((m = find_mix(port, mix->port.port_id)) == NULL) + if (!pw_map_has_item(&impl->io_map, mix->id)) return -EINVAL; if (impl->resource && impl->resource->version >= 4) @@ -1471,7 +1474,13 @@ static int port_release_mix(void *data, struct pw_impl_port_mix *mix) mix->port.port_id, SPA_ID_INVALID, NULL); pw_map_remove(&impl->io_map, mix->id); - free_mix(port, m); + + m = find_mix(port, mix->port.port_id); + if (m && m->impl_mix_id == mix->id) + free_mix(port, m); + else + pw_log_debug("%p: already cleared mix id:%d port-id:%d", + impl, mix->id, mix->port.port_id); return 0; }