Skip to content

Commit

Permalink
crash reporter: add EarlyExceptionsQueue
Browse files Browse the repository at this point in the history
`util.send_exception_to_crash_reporter` is now useful and can be transparently
used even before the exception hook is set up.
  • Loading branch information
SomberNight committed Nov 5, 2021
1 parent e0246b3 commit c331c31
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 8 deletions.
38 changes: 38 additions & 0 deletions electrum/base_crash_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import locale
import traceback
import sys
import queue

from .version import ELECTRUM_VERSION
from . import constants
Expand Down Expand Up @@ -131,6 +132,43 @@ def get_wallet_type(self) -> str:
raise NotImplementedError


class EarlyExceptionsQueue:
"""Helper singleton for explicitly sending exceptions to crash reporter.
Typically the GUIs set up an "exception hook" that catches all otherwise
uncaught exceptions (which unroll the stack of a thread completely).
This class provides methods to report *any* exception, and queueing logic
that delays processing until the exception hook is set up.
"""

_is_exc_hook_ready = False
_exc_queue = queue.Queue()

@classmethod
def set_hook_as_ready(cls):
if cls._is_exc_hook_ready:
return
cls._is_exc_hook_ready = True
while cls._exc_queue.qsize() > 0:
e = cls._exc_queue.get()
cls._send_exception_to_crash_reporter(e)

@classmethod
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)

@staticmethod
def _send_exception_to_crash_reporter(e: BaseException):
assert EarlyExceptionsQueue._is_exc_hook_ready
sys.excepthook(type(e), e, e.__traceback__)


send_exception_to_crash_reporter = EarlyExceptionsQueue.send_exception_to_crash_reporter


def trigger_crash():
# note: do not change the type of the exception, the message,
# or the name of this method. All reports generated through this
Expand Down
3 changes: 0 additions & 3 deletions electrum/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,6 @@ def __init__(self, config: SimpleConfig, fd=None, *, listen_jsonrpc=True):
if self.config.get('use_gossip', False):
self.network.start_gossip()

self.exception = None # type: Optional[Exception]

self._stop_entered = False
self._stopping_soon_or_errored = threading.Event()
self._stopped_event = threading.Event()
Expand All @@ -508,7 +506,6 @@ async def _run(self, jobs: Iterable = None):
raise
except Exception as e:
self.logger.exception("taskgroup died.")
self.exception = e
util.send_exception_to_crash_reporter(e)
finally:
self.logger.info("taskgroup stopped.")
Expand Down
3 changes: 2 additions & 1 deletion electrum/gui/kivy/uix/dialogs/crash_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from electrum.gui.kivy.i18n import _

from electrum.base_crash_reporter import BaseCrashReporter
from electrum.base_crash_reporter import BaseCrashReporter, EarlyExceptionsQueue
from electrum.logging import Logger


Expand Down Expand Up @@ -185,6 +185,7 @@ def __init__(self, main_window):
base.ExceptionManager.add_handler(self)
# For everything else:
sys.excepthook = lambda exctype, value, tb: self.handle_exception(value)
EarlyExceptionsQueue.set_hook_as_ready()

def handle_exception(self, _inst):
exc_info = sys.exc_info()
Expand Down
2 changes: 0 additions & 2 deletions electrum/gui/qt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,6 @@ def main(self):
signal.signal(signal.SIGINT, lambda *args: self.app.quit())
# hook for crash reporter
Exception_Hook.maybe_setup(config=self.config)
if self.daemon.exception: # if daemon errored too early, replay that now:
send_exception_to_crash_reporter(self.daemon.exception)
# first-start network-setup
try:
self.init_network()
Expand Down
3 changes: 2 additions & 1 deletion electrum/gui/qt/exception_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
QMessageBox, QHBoxLayout, QVBoxLayout)

from electrum.i18n import _
from electrum.base_crash_reporter import BaseCrashReporter
from electrum.base_crash_reporter import BaseCrashReporter, EarlyExceptionsQueue
from electrum.logging import Logger
from electrum import constants
from electrum.network import Network
Expand Down Expand Up @@ -172,6 +172,7 @@ def __init__(self, *, config: 'SimpleConfig'):

sys.excepthook = self.handler
self._report_exception.connect(_show_window)
EarlyExceptionsQueue.set_hook_as_ready()

@classmethod
def maybe_setup(cls, *, config: 'SimpleConfig', wallet: 'Abstract_Wallet' = None) -> None:
Expand Down
3 changes: 2 additions & 1 deletion electrum/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,8 @@ def run_with_except_hook(*args2, **kwargs2):


def send_exception_to_crash_reporter(e: BaseException):
sys.excepthook(type(e), e, e.__traceback__)
from .base_crash_reporter import send_exception_to_crash_reporter
send_exception_to_crash_reporter(e)


def versiontuple(v):
Expand Down

0 comments on commit c331c31

Please sign in to comment.