diff --git a/accounts/usbwallet/hub.go b/accounts/usbwallet/hub.go index 8f34d63e8..23be98a08 100644 --- a/accounts/usbwallet/hub.go +++ b/accounts/usbwallet/hub.go @@ -20,6 +20,7 @@ import ( "errors" "runtime" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/accounts" @@ -64,6 +65,7 @@ type Hub struct { // TODO(karalabe): remove if hotplug lands on Windows commsPend int // Number of operations blocking enumeration commsLock sync.Mutex // Lock protecting the pending counter and enumeration + enumFails uint32 // Number of times enumeration has failed } // NewLedgerHub creates a new hardware wallet manager for Ledger devices. @@ -138,6 +140,10 @@ func (hub *Hub) refreshWallets() { if elapsed < refreshThrottling { return } + // If USB enumeration is continually failing, don't keep trying indefinitely + if atomic.LoadUint32(&hub.enumFails) > 2 { + return + } // Retrieve the current list of USB wallet devices var devices []usb.DeviceInfo @@ -156,13 +162,17 @@ func (hub *Hub) refreshWallets() { } infos, err := usb.Enumerate(hub.vendorID, 0) if err != nil { + failcount := atomic.AddUint32(&hub.enumFails, 1) if runtime.GOOS == "linux" { // See rationale before the enumeration why this is needed and only on Linux. hub.commsLock.Unlock() } - log.Error("error enumerating USB enumeration: ", "code", err) + log.Error("Failed to enumerate USB devices", "hub", hub.scheme, + "vendor", hub.vendorID, "failcount", failcount, "err", err) return } + atomic.StoreUint32(&hub.enumFails, 0) + for _, info := range infos { for _, id := range hub.productIDs { // Windows and Macos use UsageID matching, Linux uses Interface matching