From d4a07d48e817888cb0ea3a31eab16e3ce61ce762 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Thu, 30 Oct 2025 21:15:42 -0400 Subject: [PATCH] fix: resolve deadlock between interface online and Transport.identity loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move self.online = True BEFORE waiting for Transport.identity to break circular dependency. Reticulum loads Transport.identity only after interfaces are online, so blocking before self.online = True creates infinite wait. New sequence: 1. Set self.online = True (unblocks Reticulum startup) 2. Reticulum loads Transport.identity from storage 3. Wait completes successfully 4. Identity set on GATT server 5. GATT server starts with valid 16-byte identity Reduced timeout from 30s to 10s since identity should load within 1s once interface is online. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/RNS/Interfaces/BLEInterface.py | 34 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/RNS/Interfaces/BLEInterface.py b/src/RNS/Interfaces/BLEInterface.py index f8fd355..5e8b106 100644 --- a/src/RNS/Interfaces/BLEInterface.py +++ b/src/RNS/Interfaces/BLEInterface.py @@ -488,22 +488,6 @@ class BLEInterface(Interface): else: RNS.log(f"{self} central mode disabled, skipping peer discovery", RNS.LOG_INFO) - # Protocol v2: Wait for Transport.identity BEFORE starting GATT server - # This ensures the Identity characteristic is created with a valid value, - # preventing BlueZ from rejecting/corrupting the advertisement - if self.gatt_server: - RNS.log(f"{self} Waiting for Transport.identity before starting GATT server...", RNS.LOG_DEBUG) - identity_hash = self._wait_for_transport_identity(timeout=30) - if identity_hash: - self.gatt_server.set_transport_identity(identity_hash) - RNS.log(f"{self} Transport.identity set on GATT server: {identity_hash.hex()}", RNS.LOG_INFO) - else: - RNS.log(f"{self} WARNING: Starting GATT server without identity (Protocol v1 mode)", RNS.LOG_WARNING) - - # Start GATT server if peripheral mode is enabled - if self.gatt_server: - asyncio.run_coroutine_threadsafe(self._start_server(), self.loop) - # Start periodic cleanup task (CRITICAL #2: prevent unbounded reassembly buffer growth) asyncio.run_coroutine_threadsafe(self._periodic_cleanup(), self.loop) @@ -514,7 +498,25 @@ class BLEInterface(Interface): # TODO: Remove when upstream Transport.py is fixed (see session notes) self._clear_stale_ble_paths() + # Set interface online FIRST to allow Reticulum to complete startup + # (Transport.identity is loaded after interfaces are online) self.online = True + RNS.log(f"{self} interface online, waiting for Transport.identity...", RNS.LOG_INFO) + + # Protocol v2: Wait for Transport.identity BEFORE starting GATT server + # This ensures the Identity characteristic is created with a valid value, + # preventing BlueZ from rejecting/corrupting the advertisement + if self.gatt_server: + identity_hash = self._wait_for_transport_identity(timeout=10) + if identity_hash: + self.gatt_server.set_transport_identity(identity_hash) + RNS.log(f"{self} Transport.identity set on GATT server: {identity_hash.hex()}", RNS.LOG_INFO) + else: + RNS.log(f"{self} WARNING: Starting GATT server without identity (Protocol v1 mode)", RNS.LOG_WARNING) + + # Start GATT server AFTER identity is set + asyncio.run_coroutine_threadsafe(self._start_server(), self.loop) + RNS.log(f"{self} started successfully", RNS.LOG_INFO) def _run_async_loop(self):