* [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes
@ 2026-10-06 10:59 dt
2026-10-06 11:00 ` [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready dt
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: dt @ 2026-10-06 10:59 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org; +Cc: Luiz Augusto von Dentz
Hi Luiz,
This v2 rebases the BAP Release/reacquire fixes onto master
7edaa61403390fe1cf2f1fb6d45fdd90fe6e93b3 after the v1 CI PR expired:
https://github.com/bluez/bluez/pull/2550
The first fix prevents a late ready event from replying to Release with
an Acquire payload and losing the pending Disable request. The second
allows deferred IO recreation when a new Enable arrives before the old
CIS has finished disconnecting.
Changes since v1:
- Rebased both fixes and the regression test onto current master.
- Clarified the test's reply barriers in its description and comments.
- Added source-history-verified Fixes and Assisted-by attribution tags.
Regarding the sequencing review: the test waits for both initial Acquire
replies before Release, and for both Release replies before reacquiring.
Every following Acquire also completes before the next Release. Only
calls on different transport paths run concurrently, as in the existing
acquisition test; successive operations on one path are not queued
without waiting for its previous reply.
Fresh validation on this base:
- Current master plus the test: all three pause variants fail with
malformed Release replies and pending-Disable cleanup crashes.
- Both fixes: all 10 selected BAP functional cases pass.
- ASan/UBSan: coordinated-set creation with SC and legacy pairing, plus
coordinated-set acquisition, pass including teardown (3 cases).
- make check: all 35 unit-test executables pass, including 697 BAP cases.
- A separate 500 ms userspace-disconnect delay fixture isolates patch 2:
with only patch 1, both reacquires time out after 26 seconds; with both
fixes, they complete in about 375 ms and both transports become active.
This diagnostic instrumentation is excluded from the series.
The v1 functional job failed in coordinated-set cleanup, while its new
resume cases passed. This base includes eb82d81bf26b and 8a1c53517399,
which address the recorded adapter-list and BAP-session lifetime stacks;
the fresh sanitizer checks above cover those previously failing paths.
These are virtual-controller lifecycle tests, not acoustic, full-duplex
range, or physical-earbud validation. The ordinary resume test does not
force the delayed-disconnect ordering exercised by the separate fixture.
Derek
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready 2026-10-06 10:59 [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes dt @ 2026-10-06 11:00 ` dt 2026-10-06 16:43 ` BAP transport Release and reacquire fixes bluez.test.bot 2026-10-06 11:00 ` [PATCH BlueZ v2 2/3] bap: Recreate stream IO after an early Enable dt ` (2 subsequent siblings) 3 siblings, 1 reply; 6+ messages in thread From: dt @ 2026-10-06 11:00 UTC (permalink / raw) To: linux-bluetooth@vger.kernel.org; +Cc: Luiz Augusto von Dentz From: Derek Tern <1263187-dt@users.noreply.gitlab.freedesktop.org> A late stream-ready event can reach bap_resume_complete() after Release has queued Disable. It then replies to Release with an Acquire payload and drops the Disable request ID. Client disconnection can subsequently free the owner while the Disable callback still refers to it. Only complete pending Acquire/TryAcquire requests from this path. Leave Release and its request ID for the Disable callback or cancellation. Fixes: 466fce0209a3 ("transport: handle BAP Enabling state correctly when resuming") Assisted-by: Codex:GPT-6 --- profiles/audio/transport.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 8cfc98a52..e001f7315 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -1965,8 +1965,16 @@ static void bap_resume_complete(struct media_transport *transport) if (!owner) return; - if (owner->pending) + if (owner->pending) { + const char *member; + + member = dbus_message_get_member(owner->pending->msg); + /* A late ready event must not complete a pending Release. */ + if (strcmp(member, "Acquire") && strcmp(member, "TryAcquire")) + return; + owner->pending->id = 0; + } if (transport->fd < 0) { media_transport_remove_owner(transport); -- 2.56.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: BAP transport Release and reacquire fixes 2026-10-06 11:00 ` [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready dt @ 2026-10-06 16:43 ` bluez.test.bot 0 siblings, 0 replies; 6+ messages in thread From: bluez.test.bot @ 2026-10-06 16:43 UTC (permalink / raw) To: linux-bluetooth, derektern [-- Attachment #1: Type: text/plain, Size: 1022 bytes --] This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/series/1180235/ ---Test result--- Test Summary: CheckPatch PASS 1.23 seconds GitLint PASS 1.21 seconds BuildEll PASS 19.40 seconds BluezMake PASS 392.20 seconds MakeCheck PASS 14.09 seconds MakeDistcheck PASS 138.44 seconds CheckValgrind PASS 229.50 seconds CheckSmatch PASS 287.01 seconds bluezmakeextell PASS 92.95 seconds TestFunctional PASS 1139.30 seconds IncrementalBuild PASS 397.83 seconds ScanBuild PASS 1103.29 seconds https://github.com/bluez/bluez/pull/2629 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH BlueZ v2 2/3] bap: Recreate stream IO after an early Enable 2026-10-06 10:59 [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes dt 2026-10-06 11:00 ` [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready dt @ 2026-10-06 11:00 ` dt 2026-10-06 11:01 ` [PATCH BlueZ v2 3/3] test: Cover BAP transport release and reacquire dt 2026-10-07 18:40 ` [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes patchwork-bot+bluetooth 3 siblings, 0 replies; 6+ messages in thread From: dt @ 2026-10-06 11:00 UTC (permalink / raw) To: linux-bluetooth@vger.kernel.org; +Cc: Luiz Augusto von Dentz From: Derek Tern <1263187-dt@users.noreply.gitlab.freedesktop.org> When reacquiring a transport, the stream can reach Enabling before its previous CIS finishes disconnecting. Once teardown completes, IO recreation accepts only QoS, while CIS enabling requires existing IO. The pending Acquire consequently stalls. Allow deferred IO recreation in Enabling too. Keep the existing CIG-busy checks and recreate all IO before enabling CISes. Fixes: 7feff47a9fbe ("bap: delay QoS & IO creation if CIG is busy or setups configuring") Assisted-by: Codex:GPT-6 --- profiles/audio/bap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 928796e1e..a0e0ba60d 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -2576,12 +2576,17 @@ static void update_cig_setup_io(void *data, void *match_data) struct update_cig_data *info = match_data; struct bt_bap_stream *stream = setup->stream; struct bt_bap_qos *qos = bt_bap_stream_get_qos(stream); + uint8_t state; if (qos && qos->ucast.cig_id != info->cig) return; if (!setup->want_io || !stream || setup->io || setup->closing) return; - if (bt_bap_stream_get_state(stream) != BT_BAP_STREAM_STATE_QOS) + + /* Enable may complete while the previous IO is still disconnecting. */ + state = bt_bap_stream_get_state(stream); + if (state != BT_BAP_STREAM_STATE_QOS && + state != BT_BAP_STREAM_STATE_ENABLING) return; DBG("%p", setup); -- 2.56.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH BlueZ v2 3/3] test: Cover BAP transport release and reacquire 2026-10-06 10:59 [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes dt 2026-10-06 11:00 ` [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready dt 2026-10-06 11:00 ` [PATCH BlueZ v2 2/3] bap: Recreate stream IO after an early Enable dt @ 2026-10-06 11:01 ` dt 2026-10-07 18:40 ` [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes patchwork-bot+bluetooth 3 siblings, 0 replies; 6+ messages in thread From: dt @ 2026-10-06 11:01 UTC (permalink / raw) To: linux-bluetooth@vger.kernel.org; +Cc: Luiz Augusto von Dentz From: Derek Tern <1263187-dt@users.noreply.gitlab.freedesktop.org> Acquire both unicast transports, close their sockets and release them through the same D-Bus owner. Require an empty Release reply so a late ready callback cannot pass unnoticed by returning an Acquire payload. Wait for both Acquire replies before Release, and for both Release replies before the next Acquire. Only requests on different transport paths are concurrent; no path has successive operations queued without waiting for its preceding reply. Repeat three times with immediate, 100 ms and one-second reacquisition. Check Acquire reply types and active transport states. Close returned FDs even when a reply is malformed. Assisted-by: Codex:GPT-6 --- doc/functional-bap.rst | 23 ++++++++ test/functional/test_bap.py | 103 ++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/doc/functional-bap.rst b/doc/functional-bap.rst index 74a6604ad..42fa7fda8 100644 --- a/doc/functional-bap.rst +++ b/doc/functional-bap.rst @@ -105,6 +105,29 @@ test_bap_unicast_transport_acquire be established, as `bluetoothd` sets up the ISO listener on its own when the stream is enabled. +test_bap_unicast_transport_resume[0|0.1|1.0] +------------------------------------------ + +:Setup: As above, with both transports already created. + +:Steps: + 1. Acquire both transports through one D-Bus connection and wait for + both replies. + 2. Close both acquired sockets and call ``MediaTransport1.Release`` + for both transports. Requests on different paths may be in flight + together; wait for both Release replies before the next step. + 3. Reacquire immediately or after 0.1 or 1 second, and wait for both + Acquire replies before continuing. + 4. Repeat the release/reacquire cycle three times. + +:Expected: Each ``Release`` succeeds with an empty reply. Every ``Acquire`` + returns an FD and MTUs, and both transports become active again. + +:Notes: D-Bus is used directly to check the Release reply signature and + close the client sockets before releasing the transports. A late ready + callback must not answer a pending Release with an Acquire payload. + These tests do not force ISO disconnection to overlap the next Enable. + test_bap_unicast_reconfigure_metadata[empty|media] ------------------------------------------------ diff --git a/test/functional/test_bap.py b/test/functional/test_bap.py index 8d0b4489d..c4bd5fc6a 100644 --- a/test/functional/test_bap.py +++ b/test/functional/test_bap.py @@ -4,6 +4,7 @@ Tests for BAP (LE Audio) using bluetoothctl in VM instances """ +import os import threading import time import warnings @@ -282,6 +283,108 @@ def test_bap_unicast_transport_acquire(unicast_hosts): ) +def resume_transports(paths, delay): + """Wait for each operation on all CIS before starting the next one.""" + bus = None + interfaces = [] + fds = {} + + @mainloop_wrap + def setup(): + nonlocal bus, interfaces + bus = get_dbus(private=True) + interfaces = [ + dbus.Interface( + bus.get_object("org.bluez", path, introspect=False), + "org.bluez.MediaTransport1", + ) + for path in paths + ] + + def operation(method): + done = threading.Event() + replies = [] + errors = [] + + def finished(index, error=None, values=()): + replies.append(index) + if error is not None: + errors.append((paths[index], str(error))) + elif method == "Acquire" and tuple(type(value) for value in values) == ( + dbus.types.UnixFd, + dbus.UInt16, + dbus.UInt16, + ): + fds[index] = values[0].take() + elif method == "Acquire" or values: + # Release has an empty reply: a late ready callback must not + # answer it with an Acquire payload. Dispose of any stray FDs. + for value in values: + if isinstance(value, dbus.types.UnixFd): + os.close(value.take()) + errors.append((paths[index], f"invalid {method} reply")) + if len(replies) == len(paths): + done.set() + + @mainloop_wrap + def submit(): + for index, interface in enumerate(interfaces): + if method == "Release": + os.close(fds.pop(index)) + getattr(interface, method)( + reply_handler=lambda *values, i=index: finished(i, values=values), + error_handler=lambda error, i=index: finished(i, error=error), + timeout=DEFAULT_TIMEOUT, + ) + + submit() + # Different transport paths may have requests in flight together, but + # wait for every reply before another operation uses any of them. + assert done.wait(DEFAULT_TIMEOUT + 1), f"{method} did not complete" + assert not errors, (method, errors) + + @mainloop_wrap + def check_active(): + objects = dbus.Interface( + bus.get_object("org.bluez", "/"), + "org.freedesktop.DBus.ObjectManager", + ).GetManagedObjects() + for path in paths: + assert objects[path]["org.bluez.MediaTransport1"]["State"] == "active" + + @mainloop_wrap + def cleanup(): + for fd in fds.values(): + os.close(fd) + fds.clear() + if bus is not None: + bus.close() + + try: + setup() + operation("Acquire") + check_active() + for _ in range(3): + # Acquire has completed on both paths before Release starts. + # Release also waits for both replies before the next Acquire. + operation("Release") + if delay: + time.sleep(delay) + operation("Acquire") + check_active() + finally: + cleanup() + + +@unicast_host_config +@pytest.mark.parametrize("delay", [0, 0.1, 1.0]) +def test_bap_unicast_transport_resume(unicast_hosts, delay): + host0, host1, initiator, acceptor = unicast_hosts + transports = expect_transports(initiator) + expect_transports(acceptor) + host0.call(resume_transports, transports, delay) + + def clear_remote_transports(remote): """Release the peer ASEs while retaining the connected GATT session.""" done = threading.Event() -- 2.56.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes 2026-10-06 10:59 [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes dt ` (2 preceding siblings ...) 2026-10-06 11:01 ` [PATCH BlueZ v2 3/3] test: Cover BAP transport release and reacquire dt @ 2026-10-07 18:40 ` patchwork-bot+bluetooth 3 siblings, 0 replies; 6+ messages in thread From: patchwork-bot+bluetooth @ 2026-10-07 18:40 UTC (permalink / raw) To: dt; +Cc: linux-bluetooth, luiz.dentz Hello: This series was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>: On Tue, 06 Oct 2026 10:59:41 +0000 you wrote: > Hi Luiz, > > This v2 rebases the BAP Release/reacquire fixes onto master > 7edaa61403390fe1cf2f1fb6d45fdd90fe6e93b3 after the v1 CI PR expired: > https://github.com/bluez/bluez/pull/2550 > > The first fix prevents a late ready event from replying to Release with > an Acquire payload and losing the pending Disable request. The second > allows deferred IO recreation when a new Enable arrives before the old > CIS has finished disconnecting. > > [...] Here is the summary with links: - [BlueZ,v2,1/3] transport: Preserve Release on late BAP ready https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=d852faf0b1d1 - [BlueZ,v2,2/3] bap: Recreate stream IO after an early Enable https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=47f783ff5ba4 - [BlueZ,v2,3/3] test: Cover BAP transport release and reacquire https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=4b44e0726c6f You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-07 18:40 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-06 10:59 [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes dt 2026-10-06 11:00 ` [PATCH BlueZ v2 1/3] transport: Preserve Release on late BAP ready dt 2026-10-06 16:43 ` BAP transport Release and reacquire fixes bluez.test.bot 2026-10-06 11:00 ` [PATCH BlueZ v2 2/3] bap: Recreate stream IO after an early Enable dt 2026-10-06 11:01 ` [PATCH BlueZ v2 3/3] test: Cover BAP transport release and reacquire dt 2026-10-07 18:40 ` [PATCH BlueZ v2 0/3] BAP transport Release and reacquire fixes patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox