From 06ba2f792de42572ac66cf4276a44667c45207c8 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 5 May 2026 11:37:18 +0200 Subject: [PATCH] bluez5: handle fd allocation errors For the timers, only set the data after we allocated the fd because this is checked to free the fd again later. --- spa/plugins/bluez5/backend-native.c | 8 +++++-- spa/plugins/bluez5/bluez5-dbus.c | 16 +++++++++---- spa/plugins/bluez5/media-sink.c | 36 +++++++++++++++++++++-------- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/spa/plugins/bluez5/backend-native.c b/spa/plugins/bluez5/backend-native.c index 43176330f..d55977185 100644 --- a/spa/plugins/bluez5/backend-native.c +++ b/spa/plugins/bluez5/backend-native.c @@ -3334,13 +3334,17 @@ static int codec_switch_start_timer(struct rfcomm *rfcomm, int timeout_msec) { struct impl *backend = rfcomm->backend; struct itimerspec ts; + int res; spa_log_debug(backend->log, "rfcomm %p: start timer", rfcomm); if (rfcomm->timer.data == NULL) { + res = spa_system_timerfd_create(backend->main_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if (res < 0) + return res; + rfcomm->timer.fd = res; rfcomm->timer.data = rfcomm; rfcomm->timer.func = codec_switch_timer_event; - rfcomm->timer.fd = spa_system_timerfd_create(backend->main_system, - CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); rfcomm->timer.mask = SPA_IO_IN; rfcomm->timer.rmask = 0; spa_loop_add_source(backend->main_loop, &rfcomm->timer); diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index 063ae2468..88070e1f8 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -2265,13 +2265,17 @@ static int device_start_timer(struct spa_bt_device *device) { struct spa_bt_monitor *monitor = device->monitor; struct itimerspec ts; + int res; spa_log_debug(monitor->log, "device %p: start timer", device); if (device->timer.data == NULL) { + res = spa_system_timerfd_create(monitor->main_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if (res < 0) + return res; + device->timer.fd = res; device->timer.data = device; device->timer.func = device_timer_event; - device->timer.fd = spa_system_timerfd_create(monitor->main_system, - CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); device->timer.mask = SPA_IO_IN; device->timer.rmask = 0; spa_loop_add_source(monitor->main_loop, &device->timer); @@ -3538,11 +3542,15 @@ static int start_timeout_timer(struct spa_bt_monitor *monitor, time_t timeout_msec, void *data) { struct itimerspec ts; + int res; if (timer->data == NULL) { + res = spa_system_timerfd_create( + monitor->main_system, CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if (res < 0) + return res; + timer->fd = res; timer->data = data; timer->func = timer_event; - timer->fd = spa_system_timerfd_create( - monitor->main_system, CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); timer->mask = SPA_IO_IN; timer->rmask = 0; spa_loop_add_source(monitor->main_loop, timer); diff --git a/spa/plugins/bluez5/media-sink.c b/spa/plugins/bluez5/media-sink.c index 02108c375..84f3f24f1 100644 --- a/spa/plugins/bluez5/media-sink.c +++ b/spa/plugins/bluez5/media-sink.c @@ -2549,6 +2549,7 @@ impl_init(const struct spa_handle_factory *factory, struct impl *this; struct port *port; const char *str; + int res; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -2671,22 +2672,37 @@ impl_init(const struct spa_handle_factory *factory, spa_bt_transport_add_listener(this->transport, &this->transport_listener, &transport_events, this); - this->timerfd = spa_system_timerfd_create(this->data_system, - CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if ((res = spa_system_timerfd_create(this->data_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK)) < 0) + return res; + this->timerfd = res; - this->flush_timerfd = spa_system_timerfd_create(this->data_system, - CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if ((res = spa_system_timerfd_create(this->data_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK)) < 0) + goto error_close_timerfd; + this->flush_timerfd = res; if (this->codec->kind == MEDIA_CODEC_ASHA) { this->asha = calloc(1, sizeof(struct spa_bt_asha)); - if (this->asha == NULL) - return -ENOMEM; - - this->asha->timerfd = spa_system_timerfd_create(this->data_system, - CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if (this->asha == NULL) { + res = -errno; + goto error_close_flush_timerfd; + } + if ((res = spa_system_timerfd_create(this->data_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK)) < 0) + goto error_free_asha; + this->asha->timerfd = res; } - return 0; + +error_free_asha: + free(this->asha); + this->asha = NULL; +error_close_flush_timerfd: + spa_system_close(this->data_system, this->flush_timerfd); +error_close_timerfd: + spa_system_close(this->data_system, this->timerfd); + return res; } static const struct spa_interface_info impl_interfaces[] = {