electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 7a4acb05f2c9e21a738cffde712b5d8cd6eca783
parent bf067f7558657edd31b2dd7e6b30f0243cda528a
Author: SomberNight <somber.night@protonmail.com>
Date:   Wed,  8 Apr 2020 18:46:28 +0200

hww: fix threading issue in DeviceMgr: enumerate_func needs self.lock

E | gui.qt.main_window.[test_ms_p2wsh_2of3_cc3132_trezort_cc3133] | on_error
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\util.py", line 794, in run
    result = task.task()
  File "...\electrum\electrum\plugins\hw_wallet\qt.py", line 232, in trigger_pairings
    devices = devmgr.scan_devices()
  File "...\electrum\electrum\plugin.py", line 376, in func_wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\plugin.py", line 656, in scan_devices
    for f in self.enumerate_func:
RuntimeError: Set changed size during iteration

Diffstat:
Melectrum/plugin.py | 9++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/electrum/plugin.py b/electrum/plugin.py @@ -364,7 +364,7 @@ class DeviceMgr(ThreadJob): # pair. self.recognised_hardware = set() # Custom enumerate functions for devices we don't know about. - self.enumerate_func = set() + self._enumerate_func = set() # Needs self.lock. # locks: if you need to take multiple ones, acquire them in the order they are defined here! self._scan_lock = threading.RLock() self.lock = threading.RLock() @@ -395,7 +395,8 @@ class DeviceMgr(ThreadJob): self.recognised_hardware.add(pair) def register_enumerate_func(self, func): - self.enumerate_func.add(func) + with self.lock: + self._enumerate_func.add(func) def create_client(self, device: 'Device', handler: Optional['HardwareHandlerBase'], plugin: 'HW_PluginBase') -> Optional['HardwareClientBase']: @@ -664,7 +665,9 @@ class DeviceMgr(ThreadJob): devices = self._scan_devices_with_hid() # Let plugin handlers enumerate devices we don't know about - for f in self.enumerate_func: + with self.lock: + enumerate_funcs = list(self._enumerate_func) + for f in enumerate_funcs: try: new_devices = f() except BaseException as e: