commit 371f55a0f922cf57196ae3d8d7c2fabc7a9f0f08
parent 81fc3fcce2413bae55fc3e80a43744f7743745aa
Author: SomberNight <somber.night@protonmail.com>
Date: Wed, 1 Apr 2020 21:05:19 +0200
hww: fix some threading issues in wizard
fixes #3377
related: #6064 (passphrase dialog not rendered correctly)
Diffstat:
8 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
@@ -158,6 +158,13 @@ class BaseWizard(Logger):
exc = e
self.waiting_dialog(do_upgrade, _('Upgrading wallet format...'), on_finished=on_finished)
+ def run_task_without_blocking_gui(self, task, *, msg: str = None) -> Any:
+ """Perform a task in a thread without blocking the GUI.
+ Returns the result of 'task', or raises the same exception.
+ This method blocks until 'task' is finished.
+ """
+ raise NotImplementedError()
+
def load_2fa(self):
self.data['wallet_type'] = '2fa'
self.data['use_trustedcoin'] = True
@@ -421,6 +428,7 @@ class BaseWizard(Logger):
def on_hw_derivation(self, name, device_info: 'DeviceInfo', derivation, xtype):
from .keystore import hardware_keystore
devmgr = self.plugins.device_manager
+ assert isinstance(self.plugin, HW_PluginBase)
try:
xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self)
client = devmgr.client_by_id(device_info.device.id_)
diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py
@@ -529,6 +529,26 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
if on_finished:
on_finished()
+ def run_task_without_blocking_gui(self, task, *, msg=None):
+ assert self.gui_thread == threading.current_thread(), 'must be called from GUI thread'
+ if msg is None:
+ msg = _("Please wait...")
+
+ exc = None # type: Optional[Exception]
+ res = None
+ def task_wrapper():
+ nonlocal exc
+ nonlocal res
+ try:
+ task()
+ except Exception as e:
+ exc = e
+ self.waiting_dialog(task_wrapper, msg=msg)
+ if exc is None:
+ return res
+ else:
+ raise exc
+
@wizard_dialog
def choice_dialog(self, title, message, choices, run_next):
c_values = [x[0] for x in choices]
diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py
@@ -707,7 +707,8 @@ class DigitalBitboxPlugin(HW_PluginBase):
client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard)
if purpose == HWD_SETUP_NEW_WALLET:
client.setupRunning = True
- client.get_xpub("m/44'/0'", 'standard')
+ wizard.run_task_without_blocking_gui(
+ task=lambda: client.get_xpub("m/44'/0'", 'standard'))
def is_mobile_paired(self):
diff --git a/electrum/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py
@@ -78,6 +78,8 @@ class HW_PluginBase(BasePlugin):
"""Called when creating a new wallet or when using the device to decrypt
an existing wallet. Select the device to use. If the device is
uninitialized, go through the initialization process.
+
+ Runs in GUI thread.
"""
raise NotImplementedError()
diff --git a/electrum/plugins/keepkey/keepkey.py b/electrum/plugins/keepkey/keepkey.py
@@ -279,7 +279,8 @@ class KeepKeyPlugin(HW_PluginBase):
client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard)
if not device_info.initialized:
self.initialize_device(device_id, wizard, client.handler)
- client.get_xpub('m', 'standard')
+ wizard.run_task_without_blocking_gui(
+ task=lambda: client.get_xpub("m", 'standard'))
client.used()
def get_xpub(self, device_id, derivation, xtype, wizard):
diff --git a/electrum/plugins/ledger/ledger.py b/electrum/plugins/ledger/ledger.py
@@ -591,7 +591,8 @@ class LedgerPlugin(HW_PluginBase):
def setup_device(self, device_info, wizard, purpose):
device_id = device_info.device.id_
client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard)
- client.get_xpub("m/44'/0'", 'standard') # TODO replace by direct derivation once Nano S > 1.1
+ wizard.run_task_without_blocking_gui(
+ task=lambda: client.get_xpub("m/44'/0'", 'standard')) # TODO replace by direct derivation once Nano S > 1.1
def get_xpub(self, device_id, derivation, xtype, wizard):
if xtype not in self.SUPPORTED_XTYPES:
diff --git a/electrum/plugins/safe_t/safe_t.py b/electrum/plugins/safe_t/safe_t.py
@@ -253,7 +253,8 @@ class SafeTPlugin(HW_PluginBase):
client = self.scan_and_create_client_for_device(device_id=device_id, wizard=wizard)
if not device_info.initialized:
self.initialize_device(device_id, wizard, client.handler)
- client.get_xpub('m', 'standard')
+ wizard.run_task_without_blocking_gui(
+ task=lambda: client.get_xpub("m", 'standard'))
client.used()
def get_xpub(self, device_id, derivation, xtype, wizard):
diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py
@@ -280,7 +280,8 @@ class TrezorPlugin(HW_PluginBase):
if not device_info.initialized:
self.initialize_device(device_id, wizard, client.handler)
is_creating_wallet = purpose == HWD_SETUP_NEW_WALLET
- client.get_xpub('m', 'standard', creating=is_creating_wallet)
+ wizard.run_task_without_blocking_gui(
+ task=lambda: client.get_xpub('m', 'standard', creating=is_creating_wallet))
client.used()
def get_xpub(self, device_id, derivation, xtype, wizard):