stream: don't emit drain when in progress

We keep on calling the drain event for as long as we are drained. The
application is supposed to inactivate the stream or provide more data
at some point.

Because we do this from the data thread, we use a non-blocking invoke.
If for some reason the event callback takes a long time we might place a
lot of these invoke calls into the invoke queue, which will then be
dispatched one after another (and cause more blocking or a burst of
useless invoke calls).

Avoid this by only placing one drain invoke call into the queue at a
time.

Fixes #4529
This commit is contained in:
Wim Taymans 2025-01-28 16:51:10 +01:00
parent b341668fda
commit 864438e8e9
2 changed files with 17 additions and 4 deletions

View file

@ -146,6 +146,7 @@ struct filter {
unsigned int warn_mlock:1;
unsigned int trigger:1;
int in_emit_param_changed;
int pending_drain;
};
static int get_param_index(uint32_t id)
@ -989,13 +990,19 @@ do_call_drained(struct spa_loop *loop,
struct pw_filter *filter = &impl->this;
pw_log_trace("%p: drained", filter);
pw_filter_emit_drained(filter);
SPA_ATOMIC_DEC(impl->pending_drain);
return 0;
}
static void call_drained(struct filter *impl)
{
pw_loop_invoke(impl->main_loop,
do_call_drained, 1, NULL, 0, false, impl);
pw_log_info("%p: drained", impl);
if (SPA_ATOMIC_INC(impl->pending_drain) == 1) {
pw_loop_invoke(impl->main_loop,
do_call_drained, 1, NULL, 0, false, impl);
} else {
SPA_ATOMIC_DEC(impl->pending_drain);
}
}
static int impl_node_process(void *object)

View file

@ -154,6 +154,7 @@ struct stream {
unsigned int trigger_done_rt:1;
int in_set_param;
int in_emit_param_changed;
int pending_drain;
};
static int get_param_index(uint32_t id)
@ -455,14 +456,19 @@ do_call_drained(struct spa_loop *loop,
struct pw_stream *stream = &impl->this;
pw_log_trace_fp("%p: drained", stream);
pw_stream_emit_drained(stream);
SPA_ATOMIC_DEC(impl->pending_drain);
return 0;
}
static void call_drained(struct stream *impl)
{
pw_log_info("%p: drained", impl);
pw_loop_invoke(impl->main_loop,
do_call_drained, 1, NULL, 0, false, impl);
if (SPA_ATOMIC_INC(impl->pending_drain) == 1) {
pw_loop_invoke(impl->main_loop,
do_call_drained, 1, NULL, 0, false, impl);
} else {
SPA_ATOMIC_DEC(impl->pending_drain);
}
}
static int