From f9f7b11f4635d4733d3633486acbeed897a79e79 Mon Sep 17 00:00:00 2001 From: Alex Wolden Date: Tue, 5 Aug 2025 20:39:22 -0700 Subject: [PATCH] Fix event loop deadlock issue --- examples/ble_t1000_custom_vars.py | 2 +- src/meshcore/events.py | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/ble_t1000_custom_vars.py b/examples/ble_t1000_custom_vars.py index db0a153..e1aa45d 100755 --- a/examples/ble_t1000_custom_vars.py +++ b/examples/ble_t1000_custom_vars.py @@ -4,7 +4,7 @@ import asyncio from meshcore import MeshCore from meshcore import BLEConnection -ADDRESS = "T1000_S" # node ble adress or name +ADDRESS = "Meshcore-lora-py-tester" # node ble adress or name async def main () : con = BLEConnection(ADDRESS) diff --git a/src/meshcore/events.py b/src/meshcore/events.py index fc81f80..94a6643 100644 --- a/src/meshcore/events.py +++ b/src/meshcore/events.py @@ -1,4 +1,5 @@ from enum import Enum +import inspect import logging from math import log from typing import Any, Dict, Optional, Callable, List, Union @@ -133,6 +134,7 @@ class EventDispatcher: while self.running: event = await self.queue.get() logger.debug(f"Dispatching event: {event.type}, {event.payload}, {event.attributes}") + for subscription in self.subscriptions.copy(): # Check if event type matches if subscription.event_type is None or subscription.event_type == event.type: @@ -142,14 +144,23 @@ class EventDispatcher: if not all(event.attributes.get(key) == value for key, value in subscription.attribute_filters.items()): continue - try: - result = subscription.callback(event.clone()) - if asyncio.iscoroutine(result): - await result - except Exception as e: - print(f"Error in event handler: {e}") + + # Fire and forget - don't await! + asyncio.create_task(self._execute_callback(subscription.callback, event.clone())) self.queue.task_done() + + async def _execute_callback(self, callback, event): + """Execute a callback with proper error handling""" + try: + if asyncio.iscoroutinefunction(callback): + await callback(event) + else: + result = callback(event) + if inspect.iscoroutine(result): + await result + except Exception as e: + logger.error(f"Error in event handler for {event.type}: {e}", exc_info=True) async def start(self): if not self.running: