# Buggy code
def scan_devices(self) -> Sequence["Device"]:
    self.logger.info("scanning devices...")

    # First see what's connected that we know about
    devices = self._scan_devices_with_hid()

    # Let plugin handlers enumerate devices we don't know about
    with self.lock:
        enumerate_funcs = list(self._enumerate_func)
    for f in enumerate_funcs:
        # custom enumerate functions might use hidapi, so use hid thread to be safe
        new_devices_fut = _hid_executor.submit(f)
        try:
            new_devices = new_devices_fut.result()
        except BaseException as e:
            self.logger.error(
                "custom device enum failed. func {}, error {}".format(str(f), repr(e))
            )
        else:
            devices.extend(new_devices)

    # find out what was disconnected
    pairs = [(dev.path, dev.id_) for dev in devices]
    disconnected_clients = []
    with self.lock:
        connected = {}
        for client, pair in self.clients.items():
            if pair in pairs and client.has_usable_connection_with_device():
                connected[client] = pair
            else:
                disconnected_clients.append((client, pair[1]))
        self.clients = connected

    # Unpair disconnected devices
    for client, id_ in disconnected_clients:
        self.unpair_id(id_)
        if client.handler:
            client.handler.update_status(False)

    return devices


# Traceback (OSError)
$ ~/Downloads/apps/electrum-4.0.2-x86_64.AppImage --testnet
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
E | plugin.DeviceMgr | failed to create client for bitbox02 at b'0001:0009:01': Exception('No BitBox02 detected')
E | plugins.coldcard.coldcard.Coldcard_KeyStore |
Traceback (most recent call last):
File "/tmp/.mount_electrcFBIsQ/usr/lib/python3.7/site-packages/electrum/plugins/coldcard/coldcard.py", line 383, in sign_transaction
resp = client.sign_transaction_poll()
File "/tmp/.mount_electrcFBIsQ/usr/lib/python3.7/site-packages/electrum/plugins/coldcard/coldcard.py", line 233, in sign_transaction_poll
return self.dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)
File "/tmp/.mount_electrcFBIsQ/usr/lib/python3.7/site-packages/ckcc/client.py", line 139, in send_recv
buf = self.dev.read(64, timeout_ms=(timeout or 0))
File "hid.pyx", line 123, in hid.device.read
OSError: read error
double free or corruption (fasttop)
Aborted

# Fixed code
def scan_devices(self) -> Sequence["Device"]:
    self.logger.info("scanning devices...")

    # First see what's connected that we know about
    devices = self._scan_devices_with_hid()

    # Let plugin handlers enumerate devices we don't know about
    with self.lock:
        enumerate_funcs = list(self._enumerate_func)
    for f in enumerate_funcs:
        try:
            new_devices = f()
        except BaseException as e:
            self.logger.error(
                "custom device enum failed. func {}, error {}".format(str(f), repr(e))
            )
        else:
            devices.extend(new_devices)

    # find out what was disconnected
    pairs = [(dev.path, dev.id_) for dev in devices]
    disconnected_clients = []
    with self.lock:
        connected = {}
        for client, pair in self.clients.items():
            if pair in pairs and client.has_usable_connection_with_device():
                connected[client] = pair
            else:
                disconnected_clients.append((client, pair[1]))
        self.clients = connected

    # Unpair disconnected devices
    for client, id_ in disconnected_clients:
        self.unpair_id(id_)
        if client.handler:
            client.handler.update_status(False)

    return devices