From 393da557977372694e5c73f2f5429721edb962d7 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 25 Jun 2026 17:35:35 +0300 Subject: [PATCH] bluez5: backend-native: fix multiple profile registration Handling pending RegisterProfile callbacks was wrong as it forgot that there can be multiple profiles to be registered. Fix the handling by allowing several concurrent register callbacks. --- spa/plugins/bluez5/backend-native.c | 51 +++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/spa/plugins/bluez5/backend-native.c b/spa/plugins/bluez5/backend-native.c index da29d875f..4bd286328 100644 --- a/spa/plugins/bluez5/backend-native.c +++ b/spa/plugins/bluez5/backend-native.c @@ -106,7 +106,7 @@ struct impl { struct spa_dbus *dbus; DBusConnection *conn; - DBusPendingCall *pending_register_profile; + DBusPendingCall *pending_register_profile[4]; const struct media_codec * const * codecs; @@ -3683,12 +3683,40 @@ static DBusHandlerResult profile_handler(DBusConnection *c, DBusMessage *m, void return res; } +static bool pending_register_profile_push(struct impl *backend, DBusPendingCall *pending) +{ + SPA_FOR_EACH_ELEMENT_VAR(backend->pending_register_profile, p) { + if (!*p) { + *p = pending; + return true; + } + } + + return false; +} + +static DBusMessage *pending_register_profile_pop(struct impl *backend, DBusPendingCall *pending) +{ + SPA_FOR_EACH_ELEMENT_VAR(backend->pending_register_profile, p) { + if (*p == pending) + return steal_reply_and_unref(p); + } + + spa_assert_not_reached(); + return NULL; +} + +static void pending_register_profile_clear(struct impl *backend) +{ + SPA_FOR_EACH_ELEMENT_VAR(backend->pending_register_profile, p) + cancel_and_unref(p); +} + static void register_profile_reply(DBusPendingCall *pending, void *user_data) { struct impl *backend = user_data; - spa_assert(backend->pending_register_profile == pending); - spa_autoptr(DBusMessage) r = steal_reply_and_unref(&backend->pending_register_profile); + spa_autoptr(DBusMessage) r = pending_register_profile_pop(backend, pending); if (r == NULL) return; @@ -3705,6 +3733,8 @@ static void register_profile_reply(DBusPendingCall *pending, void *user_data) dbus_message_get_error_name(r)); return; } + + spa_log_debug(backend->log, "RegisterProfile() complete"); } static int register_profile(struct impl *backend, const char *profile, const char *uuid) @@ -3713,14 +3743,12 @@ static int register_profile(struct impl *backend, const char *profile, const cha DBusMessageIter it[4]; dbus_bool_t autoconnect; dbus_uint16_t version, chan, features; + DBusPendingCall *pending; const char *str; if (!(backend->enabled_profiles & spa_bt_profile_from_uuid(uuid))) return -ECANCELED; - if (backend->pending_register_profile) - return -EBUSY; - spa_log_debug(backend->log, "Registering Profile %s %s", profile, uuid); m = dbus_message_new_method_call(BLUEZ_SERVICE, "/org/bluez", @@ -3819,9 +3847,12 @@ static int register_profile(struct impl *backend, const char *profile, const cha } dbus_message_iter_close_container(&it[0], &it[1]); - backend->pending_register_profile = send_with_reply(backend->conn, m, register_profile_reply, backend); - if (!backend->pending_register_profile) + pending = send_with_reply(backend->conn, m, register_profile_reply, backend); + if (!pending || !pending_register_profile_push(backend, pending)) { + spa_log_error(backend->log, "Failed to start RegisterProfile() %s", profile); + cancel_and_unref(&pending); return -EIO; + } return 0; } @@ -3887,7 +3918,7 @@ static int backend_native_unregister_profiles(void *data) { struct impl *backend = data; - cancel_and_unref(&backend->pending_register_profile); + pending_register_profile_clear(backend); sco_close(backend); @@ -4069,7 +4100,7 @@ static int backend_native_free(void *data) struct rfcomm *rfcomm; - cancel_and_unref(&backend->pending_register_profile); + pending_register_profile_clear(backend); sco_close(backend);