stream: avoid flushing invoke before state change

A flushing invoke is dangerous because the application might have queued
a destroy, which could then be executed right while we do things.

Avoid doing the flushing invoke from the state change function. This was
done because previously we would invoke a process call when we were
working in non-RT mode. Nowadays we run the process function right from
the main thread and we don't need to invoke anymore. This also means
that we can't have pending process calls to flush out when we go to
paused. We do queue other calls, like drained and trigger-done but it
should not cause problems to let those through after the state change.
If this causes problems in the future, we can check the state before
emiting them.

Do a flushing invoke right before freeing the stream. This should be ok
because we removed all signal hooks so that the pending invokes would
not get to the app.

Fixes #5010
This commit is contained in:
Wim Taymans 2025-12-03 13:57:50 +01:00
parent e30ee9c846
commit 57e589f2e1
2 changed files with 6 additions and 5 deletions

View file

@ -507,8 +507,6 @@ static int impl_send_command(void *object, const struct spa_command *command)
case SPA_NODE_COMMAND_Suspend:
case SPA_NODE_COMMAND_Flush:
case SPA_NODE_COMMAND_Pause:
pw_loop_invoke(impl->main_loop,
NULL, 0, NULL, 0, false, impl);
if (filter->state == PW_FILTER_STATE_STREAMING && id != SPA_NODE_COMMAND_Flush) {
pw_log_debug("%p: pause", filter);
filter_set_state(filter, PW_FILTER_STATE_PAUSED, 0, NULL);
@ -1436,6 +1434,9 @@ void pw_filter_destroy(struct pw_filter *filter)
spa_hook_list_clean(&impl->hooks);
spa_hook_list_clean(&filter->listener_list);
/* Make sure there are no queued invokes from us anymore */
pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl);
filter_free(filter);
}

View file

@ -715,9 +715,6 @@ static int impl_send_command(void *object, const struct spa_command *command)
case SPA_NODE_COMMAND_Suspend:
case SPA_NODE_COMMAND_Flush:
case SPA_NODE_COMMAND_Pause:
/* this ensures we don't have any pending invokes in the queue after we
* emit the state change and/or command. */
pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl);
if (stream->state == PW_STREAM_STATE_STREAMING && id != SPA_NODE_COMMAND_Flush) {
pw_log_debug("%p: pause", stream);
stream_set_state(stream, PW_STREAM_STATE_PAUSED, 0, NULL);
@ -1796,6 +1793,9 @@ void pw_stream_destroy(struct pw_stream *stream)
spa_hook_list_clean(&impl->hooks);
spa_hook_list_clean(&stream->listener_list);
/* Make sure there are no queued invokes from us anymore */
pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl);
stream_free(stream);
}