|
12 | 12 | from types import TracebackType |
13 | 13 | from typing import Any, Final, NamedTuple |
14 | 14 |
|
| 15 | +from can import CanError |
15 | 16 | from can.bus import BusABC |
16 | 17 | from can.listener import Listener |
17 | 18 | from can.message import Message |
@@ -225,18 +226,20 @@ def _rx_thread(self, bus: BusABC) -> None: |
225 | 226 | if msg := bus.recv(self.timeout): |
226 | 227 | with self._lock: |
227 | 228 | handle_message(msg) |
228 | | - except Exception as exc: # pylint: disable=broad-except |
| 229 | + except CanError as exc: |
229 | 230 | self.exception = exc |
| 231 | + # Always notify the system when the bus fails |
230 | 232 | if self._loop is not None: |
231 | 233 | self._loop.call_soon_threadsafe(self._on_error, exc) |
232 | | - # Raise anyway |
233 | | - raise |
234 | | - elif not self._on_error(exc): |
235 | | - # If it was not handled, raise the exception here |
236 | | - raise |
237 | 234 | else: |
238 | | - # It was handled, so only log it |
239 | | - logger.debug("suppressed exception: %s", exc) |
| 235 | + self._on_error(exc) |
| 236 | + logger.error("CAN error in notifier thread: %s", exc) |
| 237 | + except Exception as exc: |
| 238 | + # Catching other runtime errors to prevent silent thread death |
| 239 | + self.exception = exc |
| 240 | + logger.critical("Unexpected error in notifier thread: %s", exc) |
| 241 | + self._on_error(exc) |
| 242 | + raise # Re-raise unexpected non-CAN errors |
240 | 243 |
|
241 | 244 | def _on_message_available(self, bus: BusABC) -> None: |
242 | 245 | if msg := bus.recv(0): |
@@ -330,7 +333,7 @@ def restart(self) -> None: |
330 | 333 | if hasattr(listener, "start"): |
331 | 334 | try: |
332 | 335 | listener.start() |
333 | | - except Exception as e: |
| 336 | + except (AttributeError, RuntimeError, TypeError, ValueError) as e: |
334 | 337 | logger.error("Failed to restart listener: %s", e) |
335 | 338 |
|
336 | 339 | def __exit__( |
|
0 commit comments