You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The NeturinoClientRescan method locks, sets rescan to nil then unlocks itself before resetting the value.
As the client state is scanning = true yet rescan = nil when the lock is released there is a race between the executing Rescan method and any NotifyReceived calls that are waiting to obtain the lock. If a NotifyReceived call picks up the lock in this state, it will panic when it tries to run rescan.Update as scanning is true.
Make a change against btcwallet to address the state management issues:
make the entire Rescan method a critical path (i.e., only unlock via a single defer call)
make the entire NotifyReceived method a critical path
remove the locking in the notificationHandler to prevent a deadlock caused by making Rescan completely critical. This locking isn't necessary as it attempts to read the state of the rescanErr channel. But if rescanErr is nil, then there is no Rescan object created yet so no errors to read. Also, reading from a nil channel will simply block but the read is wrapped in a select statement with other exits.
Risks
there are no unit tests on the neutrino client in btcwallet and even a targeted change like this is hard to know if it introduced any regressions
The text was updated successfully, but these errors were encountered:
MStreet3
changed the title
Found in unit test run:
NeutrinoClient data race
Oct 14, 2022
Problem
The
NeturinoClient
Rescan
method locks, setsrescan
tonil
then unlocks itself before resetting the value.As the client state is
scanning = true
yetrescan = nil
when the lock is released there is a race between the executingRescan
method and anyNotifyReceived
calls that are waiting to obtain the lock. If aNotifyReceived
call picks up the lock in this state, it will panic when it tries to runrescan.Update
asscanning
istrue
.https://github.com/btcsuite/btcwallet/blob/master/chain/neutrino.go#L351
Originally analyzed and found by @guggero in lightningnetwork/lnd#6985
Related Work
See PR #695
See PR #533
Solution 1
Make a change against
btcwallet
to address the state management issues:Rescan
method a critical path (i.e., only unlock via a single defer call)NotifyReceived
method a critical pathnotificationHandler
to prevent a deadlock caused by makingRescan
completely critical. This locking isn't necessary as it attempts to read the state of therescanErr
channel. But ifrescanErr
is nil, then there is noRescan
object created yet so no errors to read. Also, reading from anil
channel will simply block but the read is wrapped in a select statement with other exits.Risks
The text was updated successfully, but these errors were encountered: