Merge pull request #10910 from f321x/report_exception
What changed, and why it matters
This change tightens up Electrum's crash reporter so it cannot be flooded with an unbounded number of exceptions. Before the patch, every unhandled exception was placed in an internal queue with no size limit, which could slowly consume memory if something kept crashing. The patch caps that queue at 100 entries and logs exceptions immediately instead of silently holding them. It is a hardening fix rather than a fix for an active attack.
Treat as a routine hardening improvement. No urgent action is required, but users running daemon or long-lived instances should update to a version containing this commit to avoid potential memory pressure from repeated unhandled exceptions.
Security signals we found
Unbounded queue replaced with bounded queue
Exceptions now logged immediately instead of silently queued
Memory-growth hardening for crash-reporting path
Evidence from the diff
In electrum/base_crash_reporter.py, EarlyExceptionsQueue._exc_queue was changed from an unbounded queue.Queue() to a bounded queue.Queue(maxsize=100). send_exception_to_crash_reporter() now logs the exception via the class logger and uses put_nowait(), dropping exceptions once the queue is full. This prevents unbounded memory growth from queued exceptions when the crash-reporter hook is not yet ready or never becomes ready (e.g., daemon mode).
Changed components
electrum/base_crash_reporter.pyEarlyExceptionsQueueInspect captured patch +9 / −3
### electrum/base_crash_reporter.py
@@ -32,7 +32,7 @@
from . import constants
from .i18n import _
from .util import make_aiohttp_session, error_text_str_to_safe_str
-from .logging import describe_os_version, Logger, get_git_version
+from .logging import describe_os_version, Logger, get_logger, get_git_version
from .crypto import sha256
if TYPE_CHECKING:
@@ -221,7 +221,8 @@ class EarlyExceptionsQueue:
"""
_is_exc_hook_ready = False
- _exc_queue = queue.Queue()
+ _exc_queue = queue.Queue(maxsize=100)
+ _logger = get_logger(__name__)
@classmethod
def set_hook_as_ready(cls):
@@ -238,7 +239,12 @@ def send_exception_to_crash_reporter(cls, e: BaseException):
if cls._is_exc_hook_ready:
cls._send_exception_to_crash_reporter(e)
else:
- cls._exc_queue.put(e)
+ # The exc hook might never become ready (e.g. daemon), so log now.
+ cls._logger.error("exception passed to crash reporter (exc hook not ready):", exc_info=e)
+ try:
+ cls._exc_queue.put_nowait(e)
+ except queue.Full:
+ pass
@staticmethod
def _send_exception_to_crash_reporter(e: BaseException):Why this scored 22/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.