Skip to content

Make BLE Transport an actor to fix background discovery crashes#1554

Merged
garthvh merged 28 commits into
mainfrom
discovery-background-fixes
Jan 15, 2026
Merged

Make BLE Transport an actor to fix background discovery crashes#1554
garthvh merged 28 commits into
mainfrom
discovery-background-fixes

Conversation

@garthvh

@garthvh garthvh commented Jan 8, 2026

Copy link
Copy Markdown
Member

No description provided.

garthvh and others added 16 commits January 4, 2026 20:06
update the translations
* Don't add new BLE  devices to the device list in the backgournd

* Bump version

* Update Meshtastic/MeshtasticApp.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update Meshtastic/MeshtasticApp.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@garthvh garthvh requested a review from Copilot January 8, 2026 03:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR converts BLETransport from a class to an actor to address thread safety issues causing crashes during background discovery. The actor model ensures synchronized access to shared state across concurrent contexts.

Key changes:

  • Converted BLETransport from class to actor for thread-safe state management
  • Added async/await throughout the call chain to properly handle actor isolation
  • Wrapped synchronous delegate callbacks in Task blocks to bridge non-isolated contexts

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
protobufs Updated subproject commit reference
BLETransport.swift Converted to actor, added async/await for isolation-safe access, wrapped delegate callbacks in Tasks
BLEConnection.swift Updated disconnect methods to be async and await transport calls
Transport.swift Updated protocol to support async status/discovery for actor conformance
Connection.swift Made disconnect async in protocol
AccessoryManager+Discovery.swift Added await for async discoverDevices call

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

await setupCleanupTask()
}
cont.onTermination = { _ in
Logger.transport.error("🛜 [BLE] Discovery event stream has been canecelled.")

Copilot AI Jan 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'canecelled' to 'cancelled'.

Copilot uses AI. Check for mistakes.
Comment on lines +388 to 390
let connectTask = Task { @MainActor in
try await AccessoryManager.shared.connect(to: device, withConnection: restoredConnection, wantConfig: true, wantDatabase: true, versionCheck: true)
}

Copilot AI Jan 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling pattern has been improved by awaiting the task result and catching errors explicitly. However, consider whether the restoration flow should continue or abort when connection fails, as the current implementation logs the error but proceeds to set restoreInProgress = false in both success and failure paths.

Copilot uses AI. Check for mistakes.
Comment thread Meshtastic/Accessory/Transports/Bluetooth Low Energy/BLETransport.swift Outdated
thebentern and others added 10 commits January 8, 2026 17:06
* Initial plan

* Remove nested Task block in tapback handler

Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
…ort.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@garthvh garthvh requested a review from Copilot January 9, 2026 16:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

protocol Transport {
var type: TransportType { get }
var status: TransportStatus { get }
var status: TransportStatus { get async }

Copilot AI Jan 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protocol declares status as get async, but the conforming implementations (TCPTransport and SerialTransport) still have synchronous var status: TransportStatus properties. Only BLETransport, being an actor, might naturally support async access, but TCPTransport and SerialTransport are classes and have not been updated to provide async getters. This will cause protocol conformance errors.

Suggested change
var status: TransportStatus { get async }
var status: TransportStatus { get }

Copilot uses AI. Check for mistakes.
func send(_ data: ToRadio) async throws
func connect() async throws -> AsyncStream<ConnectionEvent>
func disconnect(withError: Error?, shouldReconnect: Bool) throws
func disconnect(withError: Error?, shouldReconnect: Bool) async throws

Copilot AI Jan 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protocol now declares disconnect as async throws, but TCPConnection and SerialConnection implementations still have synchronous func disconnect(withError:shouldReconnect:) throws methods. However, these implementations are internally calling disconnect with await, which will cause compilation errors since their method is not declared as async. BLEConnection is correctly implemented with async, but the other two implementations need to be updated.

Copilot uses AI. Check for mistakes.

// Discovers devices asynchronously. For ongoing scans (e.g., BLE), this can yield via AsyncStream.
func discoverDevices() -> AsyncStream<DiscoveryEvent>
func discoverDevices() async -> AsyncStream<DiscoveryEvent>

Copilot AI Jan 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protocol declares discoverDevices() as async, but none of the conforming implementations (BLETransport, TCPTransport, SerialTransport) have been updated to match this signature. They all still declare func discoverDevices() -> AsyncStream<DiscoveryEvent> without the async keyword. This creates a protocol conformance mismatch that will cause compilation errors or runtime issues.

Suggested change
func discoverDevices() async -> AsyncStream<DiscoveryEvent>
func discoverDevices() -> AsyncStream<DiscoveryEvent>

Copilot uses AI. Check for mistakes.
@garthvh garthvh changed the base branch from 2.7.7 to main January 12, 2026 08:12
@CLAassistant

CLAassistant commented Jan 14, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
7 out of 8 committers have signed the CLA.

✅ garthvh
✅ compumike
✅ MGJ520
✅ RCGV1
✅ thebentern
✅ matkam
✅ alvarosamudio
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

@garthvh garthvh merged commit bc39cbd into main Jan 15, 2026
1 of 2 checks passed
garthvh added a commit that referenced this pull request Jan 15, 2026
garthvh added a commit that referenced this pull request Jan 15, 2026
@garthvh garthvh deleted the discovery-background-fixes branch January 15, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants