mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
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.
This commit is contained in:
parent
15a4d9a9df
commit
0a1afa698e
1 changed files with 11 additions and 2 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue