Repository navigation
Conversation
The central manager delegate dropped the error from DidFailToConnectPeripheral and DidDisconnectPeripheral. Connect then returned a zero Device with a nil error, and the first GATT call on it panicked. Send the error along with the peripheral and return it from Connect. Fall back to a generic error when CoreBluetooth gives none, which happens when a disconnect from an earlier connection reaches a pending Connect.
acouvreur
marked this pull request as ready for review
October 17, 2026 20:44
deadprogram
reviewed
Oct 27, 2026
deadprogram
left a comment
Member
There was a problem hiding this comment.
Thanks for this. The main fix is correct. Before this change Connect returned connectionError, which is nil unless the timeout fired.
Some points:
- When a stale disconnect gets to
Connectand it returns an error, thea.cm.Connect(prphs[0], nil)call is still pending in CoreBluetooth. If that attempt then succeeds,DidConnectPeripheralfinds no channel and ignores it. The OS link stays up and noDeviceowns it. Please calla.cm.CancelConnect(prphs[0])on this error path whenconnectionError == nil. - After this change, a stale disconnect still makes the new
Connectfail, so the caller must retry. This is better than a panic, but please say it in the PR description. - The
Resetcomment still has an em dash (Connect — closing). You change the next line, so please fix this one too.
Also please test on a Mac with the steps in the description before we merge.
Member
Author
I tested on a Mac with the steps from the description. The results for the base commit and this branch are in the table in the description. |
Member
|
@acouvreur please update your last commit to remove the coding tool attritbution. Thanks. |
When the disconnect of a previous connection reaches a pending Connect, the CoreBluetooth connection attempt is still running. If it then succeeds, nothing owns the link. Cancel it on this error path. The disconnect delegate now always sends an error, since a disconnect with no CoreBluetooth error (after CancelPeripheralConnection) can reach Connect while the peripheral is already in the connecting state.
acouvreur
force-pushed
the
darwin-connect-error
branch
from
October 31, 2026 00:51
1f08ebf to
6f6b23b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #278.
On macOS,
Connectcould return a zeroDevicewith a nil error, and the first GATT call on it panicked. The central manager delegate dropped the error fromDidFailToConnectPeripheralandDidDisconnectPeripheral, andConnectonly returned its own timeout error.This happens when you connect right after
Disconnect. The disconnect of the old connection reaches the new pendingConnect, as jbanyer described in the issue.The delegate now sends the error with the peripheral. A disconnect always counts as a failure, even with no CoreBluetooth error.
Connectreturns its own timeout error first, then the CoreBluetooth error, then a generic error.When
Connectfails for a reason other than its own timeout, it cancels the pending CoreBluetooth connection. Without this, that attempt can succeed later and leave a link that noDeviceowns.A
Connectunblocked byAdapter.Resetnow returns an error instead of a zeroDevice.Behavior change
A stale disconnect still makes the new
Connectfail. It now returns an error instead of a zeroDevice, so the caller must retry. On the hardware below, one retry always connected.Testing
MacBook Pro 15,2 (Intel, BCM4364, macOS 15.8.1) with a Valve Lighthouse base station. Compared the base commit d679711 with this branch.
Disconnect(steps from #278)Deviceon the first try, then a nil pointer panicConnect failed: peripheral disconnectedin about 0.5 ms. 10/10 retries connect and find 4 servicesCancelConnect, 5/5 stay connected with noDeviceConnectionTimeouttimeout on ConnectReset5 ms into a pendingConnectDeviceConnect canceled by adapter Reset, zeroDevice