From f60e03b4efd629591d8d73757b454f5301ed9374 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 31 Jan 2026 15:23:44 +0200 Subject: [PATCH] pulse-server: use timeout also for creating sample-play streams Add 35 sec timeout for PLAY_SAMPLE streams to start streaming, similar to what we do with normal streams, and fail playback if they don't start. This avoids pending sample playback using up resources indefinitely if streams fail to start for some reason, e.g. session manager is not linking them. --- src/modules/module-protocol-pulse/defs.h | 2 ++ .../module-protocol-pulse/sample-play.c | 23 +++++++++++++++++++ .../module-protocol-pulse/sample-play.h | 3 +++ src/modules/module-protocol-pulse/stream.c | 2 +- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/modules/module-protocol-pulse/defs.h b/src/modules/module-protocol-pulse/defs.h index c333f21f5..f3e25f137 100644 --- a/src/modules/module-protocol-pulse/defs.h +++ b/src/modules/module-protocol-pulse/defs.h @@ -39,6 +39,8 @@ #define MODULE_INDEX_MASK 0xfffffffu #define MODULE_FLAG (1u << 29) +#define STREAM_CREATE_TIMEOUT (35 * SPA_NSEC_PER_SEC) + #define DEFAULT_SINK "@DEFAULT_SINK@" #define DEFAULT_SOURCE "@DEFAULT_SOURCE@" #define DEFAULT_MONITOR "@DEFAULT_MONITOR@" diff --git a/src/modules/module-protocol-pulse/sample-play.c b/src/modules/module-protocol-pulse/sample-play.c index db3893c0f..09b0e75cc 100644 --- a/src/modules/module-protocol-pulse/sample-play.c +++ b/src/modules/module-protocol-pulse/sample-play.c @@ -17,10 +17,12 @@ #include #include +#include "defs.h" #include "format.h" #include "log.h" #include "sample.h" #include "sample-play.h" +#include "internal.h" static void sample_play_stream_state_changed(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error) @@ -30,17 +32,32 @@ static void sample_play_stream_state_changed(void *data, enum pw_stream_state ol switch (state) { case PW_STREAM_STATE_UNCONNECTED: case PW_STREAM_STATE_ERROR: + pw_timer_queue_cancel(&p->timer); sample_play_emit_done(p, -EIO); break; case PW_STREAM_STATE_PAUSED: p->id = pw_stream_get_node_id(p->stream); sample_play_emit_ready(p, p->id); break; + case PW_STREAM_STATE_STREAMING: + pw_timer_queue_cancel(&p->timer); + break; default: break; } } +static void sample_play_start_timeout(void *user_data) +{ + struct sample_play *p = user_data; + + pw_log_info("timeout on sample %s", p->sample->name); + + if (p->stream) + pw_stream_set_active(p->stream, false); + sample_play_emit_done(p, -ETIMEDOUT); +} + static void sample_play_stream_destroy(void *data) { struct sample_play *p = data; @@ -163,6 +180,10 @@ struct sample_play *sample_play_new(struct pw_core *core, if (res < 0) goto error_cleanup; + /* Time out if we don't get a link; same timeout as for normal streams */ + pw_timer_queue_add(sample->impl->timer_queue, &p->timer, NULL, + STREAM_CREATE_TIMEOUT, sample_play_start_timeout, p); + return p; error_cleanup: @@ -181,6 +202,8 @@ void sample_play_destroy(struct sample_play *p) spa_hook_list_clean(&p->hooks); + pw_timer_queue_cancel(&p->timer); + free(p); } diff --git a/src/modules/module-protocol-pulse/sample-play.h b/src/modules/module-protocol-pulse/sample-play.h index a34ca9213..98af7ee29 100644 --- a/src/modules/module-protocol-pulse/sample-play.h +++ b/src/modules/module-protocol-pulse/sample-play.h @@ -11,6 +11,8 @@ #include #include +#include + struct sample; struct pw_core; struct pw_loop; @@ -41,6 +43,7 @@ struct sample_play { uint32_t offset; uint32_t stride; struct spa_hook_list hooks; + struct pw_timer timer; void *user_data; }; diff --git a/src/modules/module-protocol-pulse/stream.c b/src/modules/module-protocol-pulse/stream.c index 496bcb52c..a6beb9fd7 100644 --- a/src/modules/module-protocol-pulse/stream.c +++ b/src/modules/module-protocol-pulse/stream.c @@ -107,7 +107,7 @@ struct stream *stream_new(struct client *client, enum stream_type type, uint32_t /* Time out if we don't get a link and can't send a reply to create in 35s. Client will time out in * 30s and clean up its stream anyway. */ pw_timer_queue_add(stream->impl->timer_queue, &stream->timer, NULL, - 35 * SPA_NSEC_PER_SEC, create_stream_timeout, stream); + STREAM_CREATE_TIMEOUT, create_stream_timeout, stream); return stream;