fix: exceptions in callback should not terminate caller
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m46s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
This commit is contained in:
2025-12-07 13:07:38 +01:00
parent 97e9742c75
commit e23f8bd34c
5 changed files with 22 additions and 4 deletions

View File

@@ -6,6 +6,7 @@ Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
import asyncio
import time
from utils import safe_callback
from mfrc522 import MFRC522
try:
@@ -74,7 +75,7 @@ class Nfc:
self.last_uid = uid
self.last_uid_timestamp = time.ticks_us()
if self.cb is not None and last_callback_uid != uid:
self.cb.onTagChange(uid)
safe_callback(lambda: self.cb.onTagChange(uid), "nfc tag change")
last_callback_uid = uid
await asyncio.sleep_ms(poll_interval_ms)

View File

@@ -1,6 +1,7 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
from utils.helpers import safe_callback
from utils.buttons import Buttons
from utils.config import Configuration
from utils.leds import LedManager
@@ -11,4 +12,4 @@ from utils.sdcontext import SDContext
from utils.timer import TimerManager
__all__ = ["BTreeDB", "BTreeFileManager", "Buttons", "Configuration", "get_pin_index", "LedManager", "MBRPartition",
"SDContext", "TimerManager"]
"safe_callback", "SDContext", "TimerManager"]

View File

@@ -5,6 +5,7 @@ import asyncio
import machine
import micropython
import time
from utils import safe_callback
try:
from typing import TYPE_CHECKING # type: ignore
except ImportError:
@@ -74,4 +75,4 @@ class Buttons:
await self.int_flag.wait()
while len(self.pressed) > 0:
what = self.pressed.pop()
self.cb.onButtonPressed(what)
safe_callback(lambda: self.cb.onButtonPressed(what), "button callback")

View File

@@ -0,0 +1,12 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
import sys
def safe_callback(func, name="callback"):
try:
func()
except Exception as ex:
print(f"Uncaught exception in {name}")
sys.print_exception(ex)

View File

@@ -4,6 +4,7 @@
import asyncio
import heapq
import time
from utils import safe_callback
TIMER_DEBUG = True
@@ -72,5 +73,7 @@ class TimerManager(object):
continue
except asyncio.TimeoutError:
pass
if len(self.timers) == 0:
continue
_, callback = heapq.heappop(self.timers)
callback()
safe_callback(callback, "timer callback")