Add timeout for write-without-response#1186
Conversation
…ReadyToSendWriteWithoutResponse is not called。 On some iOS versions/chipsets, the callback may be delayed or never fired, causing the write pipeline to stall indefinitely. Also reset canSendWriteWithoutResponse on disconnect to avoid stale state.
twyatt
left a comment
There was a problem hiding this comment.
@LuoPeiQin do you happen to know if there is any official documentation around this as an issue with Core Bluetooth? I'm worried this approach will cause loss of data for some consumers of Kable, and I'd love to see more information about why this happens and if it is a known bug with Core Bluetooth.
@twyatt Yes — this is a well-documented, long-standing CoreBluetooth issue. Here are the three most relevant references: 1. Apple Developer Forums — Apple engineer confirmed callback is not reliably deliveredAn Apple engineer confirmed that the system will not wake up an app to deliver
The reporter also observed that writing directly (ignoring 2. NordicSemiconductor/IOS-nRF-Connect-Device-Manager — Official workaround in productionNordic's official iOS BLE library (
If the industry's leading BLE chip vendor treats this callback as unreliable in their own production library, it validates the need for a timeout fallback.
3. flutter_blue_plus Issue #1331 (May 2026) — Bug confirmed on latest iOSOn iOS 26.4.2 and iOS 26.5, This confirms the problem still exists on the latest iOS versions and is not a legacy-only issue. Regarding data lossThe timeout fallback does not introduce new data loss risk:
|
twyatt
left a comment
There was a problem hiding this comment.
Looks good, we should just make the timeout configurable.
Defaults to 30ms (via defaultWriteWithoutResponseTimeout). To disable, set a sufficiently large value (e.g. Duration.INFINITE). Apple only.
twyatt
left a comment
There was a problem hiding this comment.
Looks great! Thanks for the contribution!
|
LGTM |
On some iOS versions/chipsets, the callback may be delayed or never fired, causing the write pipeline to stall indefinitely. Also reset canSendWriteWithoutResponse on disconnect to avoid stale state.
Closes #1185
Note
Medium Risk
Changes timing and fallback behavior for BLE writes without response; timeout proceeds with writes that might have been deferred, though that is the intended tradeoff to avoid permanent stalls.
Overview
Fixes indefinite stalls when issuing write-without-response on Apple targets if Core Bluetooth never invokes
peripheralIsReadyToSendWriteWithoutResponse(reported on some iOS versions/chipsets).When the peripheral is not ready, the code still waits on
canSendWriteWithoutResponse, but now wraps that wait in a 2 secondwithTimeout. On timeout it logs a warning and continues with the write instead of blocking forever.On disconnect,
PeripheralDelegate.close()now setscanSendWriteWithoutResponseback totrueso a stale “not ready” flag does not carry over to the next connection.Reviewed by Cursor Bugbot for commit 75588c2. Configure here.