Browse Source

crash reporter: in Qt subclass, do network request using WaitingDialog

so it does not block the GUI
master
SomberNight 7 years ago
parent
commit
53893be4c9
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 9
      electrum/base_crash_reporter.py
  2. 5
      electrum/gui/kivy/uix/dialogs/crash_reporter.py
  3. 30
      electrum/gui/qt/exception_window.py

9
electrum/base_crash_reporter.py

@ -31,10 +31,10 @@ from .version import ELECTRUM_VERSION
from . import constants
from .i18n import _
from .util import make_aiohttp_session
from .logging import describe_os_version
from .logging import describe_os_version, Logger
class BaseCrashReporter:
class BaseCrashReporter(Logger):
report_server = "https://crashhub.electrum.org"
config_key = "show_crash_reporter"
issue_template = """<h2>Traceback</h2>
@ -59,9 +59,10 @@ class BaseCrashReporter:
ASK_CONFIRM_SEND = _("Do you want to send this report?")
def __init__(self, exctype, value, tb):
Logger.__init__(self)
self.exc_args = (exctype, value, tb)
def send_report(self, asyncio_loop, proxy, endpoint="/crash"):
def send_report(self, asyncio_loop, proxy, endpoint="/crash", *, timeout=None):
if constants.net.GENESIS[-4:] not in ["4943", "e26f"] and ".electrum.org" in BaseCrashReporter.report_server:
# Gah! Some kind of altcoin wants to send us crash reports.
raise Exception(_("Missing report URL."))
@ -69,7 +70,7 @@ class BaseCrashReporter:
report.update(self.get_additional_info())
report = json.dumps(report)
coro = self.do_post(proxy, BaseCrashReporter.report_server + endpoint, data=report)
response = asyncio.run_coroutine_threadsafe(coro, asyncio_loop).result(5)
response = asyncio.run_coroutine_threadsafe(coro, asyncio_loop).result(timeout)
return response
async def do_post(self, proxy, url, data):

5
electrum/gui/kivy/uix/dialogs/crash_reporter.py

@ -119,8 +119,11 @@ class CrashReporter(BaseCrashReporter, Factory.Popup):
try:
loop = self.main_window.network.asyncio_loop
proxy = self.main_window.network.proxy
response = json.loads(BaseCrashReporter.send_report(self, loop, proxy, "/crash.json"))
# FIXME network request in GUI thread...
response = json.loads(BaseCrashReporter.send_report(self, loop, proxy,
"/crash.json", timeout=10))
except (ValueError, ClientError):
#self.logger.debug("", exc_info=True)
self.show_popup(_('Unable to send report'), _("Please check your network connection."))
else:
self.show_popup(_('Report sent'), response["text"])

30
electrum/gui/qt/exception_window.py

@ -33,7 +33,7 @@ from PyQt5.QtWidgets import (QWidget, QLabel, QPushButton, QTextEdit,
from electrum.i18n import _
from electrum.base_crash_reporter import BaseCrashReporter
from electrum.logging import Logger
from .util import MessageBoxMixin, read_QIcon
from .util import MessageBoxMixin, read_QIcon, WaitingDialog
class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger):
@ -96,17 +96,23 @@ class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger):
self.show()
def send_report(self):
try:
proxy = self.main_window.network.proxy
response = BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, proxy)
except BaseException as e:
self.logger.exception('There was a problem with the automatic reporting')
self.main_window.show_critical(_('There was a problem with the automatic reporting:') + '\n' +
str(e) + '\n' +
_("Please report this issue manually."))
return
QMessageBox.about(self, _("Crash report"), response)
self.close()
def on_success(response):
self.show_message(parent=self,
title=_("Crash report"),
msg=response)
self.close()
def on_failure(exc_info):
e = exc_info[1]
self.logger.error('There was a problem with the automatic reporting', exc_info=exc_info)
self.show_critical(parent=self,
msg=(_('There was a problem with the automatic reporting:') + '\n' +
str(e) + '\n' +
_("Please report this issue manually.")))
proxy = self.main_window.network.proxy
task = lambda: BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, proxy)
msg = _('Sending crash report...')
WaitingDialog(self, msg, task, on_success, on_failure)
def on_close(self):
Exception_Window._active_window = None

Loading…
Cancel
Save