cryptoadvance / specter-desktop

A desktop GUI for Bitcoin Core optimised to work with hardware wallets
MIT License
793 stars 236 forks source link

Error when Jade is being used by a different app can lead Specter to crash #2343

Open moneymanolis opened 1 year ago

moneymanolis commented 1 year ago

Below is the stack trace. The error disappeared after running in the browser:

ports = await navigator.serial.getPorts()
await ports[0].close()

We'd need to implement a check for open ports and close them if there are any in Python. Sth. like this:

import serial.tools.list_ports as list_ports
ports = list(list_ports.comports())
if len(ports) > 0:
    port = ports[0].device
    ser = serial.Serial(port)
    ser.close()

Stack trace:

[2023-06-21 17:57:05,491] DEBUG in jade: Failed to connect to Jade simulator at tcp:127.0.0.1:2222
[2023-06-21 17:57:05,491] DEBUG in jade: [Errno 61] Connection refused
Traceback (most recent call last):
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/serial/serialposix.py", line 322, in open
    self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
OSError: [Errno 16] Resource busy: '/dev/cu.usbserial-024346F8'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/manolis/.pyenv/versions/3.10.0/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/manolis/.pyenv/versions/3.10.0/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/__main__.py", line 7, in <module>
    entry_point()
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/cli/cli_server.py", line 151, in server
    init_app(app, hwibridge=hwibridge)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/server.py", line 180, in init_app
    specter.hwi = HWIBridge()
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/hwi_rpc.py", line 88, in __init__
    self.enumerate()
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/helpers.py", line 99, in wrapper_fn
    return fn(*args, **kwargs)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/hwi_rpc.py", line 121, in enumerate
    client = devcls.get_client(dev["path"], passphrase)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/devices/jade.py", line 23, in get_client
    return JadeClient(*args, **kwargs)
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/devices/hwi/jade.py", line 151, in __init__
    self.jade.connect()
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/devices/hwi/jadepy/jade.py", line 123, in connect
    self.jade.connect()
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/devices/hwi/jadepy/jade.py", line 568, in connect
    self.impl.connect()
  File "/Users/manolis/coding/repos/specter-desktop/src/cryptoadvance/specter/devices/hwi/jadepy/jade_serial.py", line 32, in connect
    self.ser = serial.Serial(
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/serial/serialutil.py", line 244, in __init__
    self.open()
  File "/Users/manolis/.pyenv/versions/.specter/lib/python3.10/site-packages/serial/serialposix.py", line 325, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 16] could not open port /dev/cu.usbserial-024346F8: [Errno 16] Resource busy: '/dev/cu.usbserial-024346F8'
Funman2 commented 1 year ago

have the same issue...

k9ert commented 1 year ago

Related but seem to look different in the logs: #818 ( tried to fix in #1748)

moneymanolis commented 1 year ago

I think this is issue is a special case of the overarching "USB devices are plugged-in while starting-up Specter"-issue. It is not HWI related but is related to the serial connection used by the Jade (which none of the other devices are using btw AFAIK).

stepansnigirev commented 1 year ago

This is a problem of any connected device that goes into the locked mode (Jade, Ledger, maybe Trezor). It is caused by this line: https://github.com/cryptoadvance/specter-desktop/blob/master/src/cryptoadvance/specter/hwi_rpc.py#L88

The reason for this line was that if we didn't run hwi.enumerate() in the main thread HWI was failing to connect to the devices in the requests afterwards. I don't know why exactly it happens, and if it was somehow fixed over the years. This hack was introduced in the very beginning when we just started implementing HWI - @kdmukai may remember.

It's worth trying to debug this issue in more detail now. Possible approaches:

stepansnigirev commented 1 year ago

@moneymanolis I tried without enumerate in __init__, seems to work fine on Linux.

Can you test on Mac and Win?

PR: https://github.com/cryptoadvance/specter-desktop/pull/2371

moneymanolis commented 1 year ago

The issue above still exists, if another app (e.g. a browser tab) is using Jade's serial port and one is trying to use the Jade in Specter.

This is the error in the UI:

image

When you try to, say, sign a transaction with a Jade, the above error does not lead to a direct crash of Specter. But, if you retry it (without closing the other app using the serial port of the Jade), Specter crashes, there is no stack trace really for this, just this in the UI:

image