Skip to content

Commit

Permalink
qt exception window: turn Exception_Hook into singleton
Browse files Browse the repository at this point in the history
related #4905
related Electron-Cash/Electron-Cash@6a3d76b

conceptually did not really make sense that the Exception_Hook kept a reference
to an ~arbitrary main window (preventing gc)
  • Loading branch information
SomberNight committed May 1, 2020
1 parent 2b1a150 commit 2105c6c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
2 changes: 1 addition & 1 deletion electrum/base_crash_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def get_report_string(self):
def get_user_description(self):
raise NotImplementedError

def get_wallet_type(self):
def get_wallet_type(self) -> str:
raise NotImplementedError


Expand Down
43 changes: 31 additions & 12 deletions electrum/gui/qt/exception_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# SOFTWARE.
import sys
import html
from typing import TYPE_CHECKING, Optional, Set

from PyQt5.QtCore import QObject
import PyQt5.QtCore as QtCore
Expand All @@ -33,16 +34,22 @@
from electrum.base_crash_reporter import BaseCrashReporter
from electrum.logging import Logger
from electrum import constants
from electrum.network import Network

from .util import MessageBoxMixin, read_QIcon, WaitingDialog

if TYPE_CHECKING:
from electrum.simple_config import SimpleConfig
from electrum.wallet import Abstract_Wallet


class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger):
_active_window = None

def __init__(self, main_window, exctype, value, tb):
def __init__(self, config: 'SimpleConfig', exctype, value, tb):
BaseCrashReporter.__init__(self, exctype, value, tb)
self.main_window = main_window
self.network = Network.get_instance()
self.config = config

QWidget.__init__(self)
self.setWindowTitle('Electrum - ' + _('An Error Occurred'))
Expand Down Expand Up @@ -115,8 +122,8 @@ def on_failure(exc_info):
f' <a href="{constants.GIT_REPO_ISSUES_URL}">on GitHub</a>.'),
rich_text=True)

proxy = self.main_window.network.proxy
task = lambda: BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, proxy)
proxy = self.network.proxy
task = lambda: BaseCrashReporter.send_report(self, self.network.asyncio_loop, proxy)
msg = _('Sending crash report...')
WaitingDialog(self, msg, task, on_success, on_failure)

Expand All @@ -125,7 +132,7 @@ def on_close(self):
self.close()

def show_never(self):
self.main_window.config.set_key(BaseCrashReporter.config_key, False)
self.config.set_key(BaseCrashReporter.config_key, False)
self.close()

def closeEvent(self, event):
Expand All @@ -136,7 +143,8 @@ def get_user_description(self):
return self.description_textfield.toPlainText()

def get_wallet_type(self):
return self.main_window.wallet.wallet_type
wallet_types = Exception_Hook._INSTANCE.wallet_types_seen
return ",".join(wallet_types)

def _get_traceback_str(self) -> str:
# The msg_box that shows the report uses rich_text=True, so
Expand All @@ -154,15 +162,26 @@ def _show_window(*args):
class Exception_Hook(QObject, Logger):
_report_exception = QtCore.pyqtSignal(object, object, object, object)

def __init__(self, main_window, *args, **kwargs):
QObject.__init__(self, *args, **kwargs)
_INSTANCE = None # type: Optional[Exception_Hook] # singleton

def __init__(self, *, config: 'SimpleConfig'):
QObject.__init__(self)
Logger.__init__(self)
if not main_window.config.get(BaseCrashReporter.config_key, default=True):
return
self.main_window = main_window
assert self._INSTANCE is None, "Exception_Hook is supposed to be a singleton"
self.config = config
self.wallet_types_seen = set() # type: Set[str]

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

@classmethod
def maybe_setup(cls, *, config: 'SimpleConfig', wallet: 'Abstract_Wallet') -> None:
if not config.get(BaseCrashReporter.config_key, default=True):
return
if not cls._INSTANCE:
cls._INSTANCE = Exception_Hook(config=config)
cls._INSTANCE.wallet_types_seen.add(wallet.wallet_type)

def handler(self, *exc_info):
self.logger.error('exception caught by crash reporter', exc_info=exc_info)
self._report_exception.emit(self.main_window, *exc_info)
self._report_exception.emit(self.config, *exc_info)
7 changes: 4 additions & 3 deletions electrum/gui/qt/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,12 @@ def __init__(self, gui_object: 'ElectrumGui', wallet: Abstract_Wallet):
self.gui_object = gui_object
self.config = config = gui_object.config # type: SimpleConfig
self.gui_thread = gui_object.gui_thread
assert wallet, "no wallet"
self.wallet = wallet

self.setup_exception_hook()

self.network = gui_object.daemon.network # type: Network
assert wallet, "no wallet"
self.wallet = wallet
self.fx = gui_object.daemon.fx # type: FxThread
self.contacts = wallet.contacts
self.tray = gui_object.tray
Expand Down Expand Up @@ -304,7 +304,8 @@ def on_version_received(v):
self._update_check_thread.start()

def setup_exception_hook(self):
Exception_Hook(self)
Exception_Hook.maybe_setup(config=self.config,
wallet=self.wallet)

def on_fx_history(self):
self.history_model.refresh('fx_history')
Expand Down

0 comments on commit 2105c6c

Please sign in to comment.