URI: 
       thww: fix threading issue in DeviceMgr: enumerate_func needs self.lock - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 7a4acb05f2c9e21a738cffde712b5d8cd6eca783
   DIR parent bf067f7558657edd31b2dd7e6b30f0243cda528a
  HTML 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:
         M electrum/plugin.py                  |       9 ++++++---
       
       1 file changed, 6 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/electrum/plugin.py b/electrum/plugin.py
       t@@ -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()
       t@@ -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']:
       t@@ -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: