Skip to content

Commit 0269710

Browse files
committed
dcrwallet: Fix spv syncer loop panic
The SPVSyncer.Run() method would not previously error out when running out of peers. Now it does, leading to an error when re-running it. This was fixed in dcrwallet, but dcrlnd needs a copy of that code (because spvLoop lives in the main package).
1 parent 23dde25 commit 0269710

File tree

1 file changed

+30
-45
lines changed

1 file changed

+30
-45
lines changed

lnwallet/dcrwallet/spvsync.go

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,19 @@ type SPVSyncer struct {
2828
cfg *SPVSyncerConfig
2929
wg sync.WaitGroup
3030

31-
mtx sync.Mutex
32-
33-
// The following fields are protected by mtx.
34-
35-
cancel func()
31+
// runCtx is canceled when Stop() is called.
32+
runCtx context.Context
33+
runCancel func()
3634
}
3735

3836
// NewSPVSyncer initializes a new syncer backed by the dcrd network in SPV
3937
// mode.
4038
func NewSPVSyncer(cfg *SPVSyncerConfig) (*SPVSyncer, error) {
39+
ctx, cancel := context.WithCancel(context.Background())
4140
return &SPVSyncer{
42-
cfg: cfg,
41+
cfg: cfg,
42+
runCtx: ctx,
43+
runCancel: cancel,
4344
}, nil
4445
}
4546

@@ -56,56 +57,45 @@ func (s *SPVSyncer) start(w *DcrWallet) error {
5657
addr := &net.TCPAddr{IP: net.ParseIP("::1"), Port: 0}
5758
amgrDir := filepath.Join(s.cfg.AppDataDir, s.cfg.Net.Name)
5859
amgr := addrmgr.New(amgrDir, lookup)
59-
lp := p2p.NewLocalPeer(s.cfg.Net, addr, amgr)
60-
if s.cfg.DialFunc != nil {
61-
lp.SetDialFunc(s.cfg.DialFunc)
62-
}
63-
lp.SetDisableRelayTx(s.cfg.DisableRelayTx)
64-
65-
syncer := spv.NewSyncer(w.wallet, lp)
66-
if len(s.cfg.Peers) > 0 {
67-
syncer.SetPersistentPeers(s.cfg.Peers)
68-
}
69-
w.wallet.SetNetworkBackend(syncer)
70-
71-
if disableDiscoverAccts {
72-
syncer.DisableDiscoverAccounts()
73-
}
74-
75-
syncer.SetNotifications(&spv.Notifications{
76-
Synced: w.onSyncerSynced,
77-
})
78-
79-
// This context will be canceled by `w` once its Stop() method is
80-
// called.
81-
ctx, cancel := context.WithCancel(context.Background())
82-
s.mtx.Lock()
83-
s.cancel = cancel
84-
s.mtx.Unlock()
8560

8661
s.wg.Add(1)
8762
go func() {
8863
defer s.wg.Done()
8964

9065
for {
9166
dcrwLog.Debugf("Starting SPV syncer")
67+
lp := p2p.NewLocalPeer(s.cfg.Net, addr, amgr)
68+
if s.cfg.DialFunc != nil {
69+
lp.SetDialFunc(s.cfg.DialFunc)
70+
}
71+
lp.SetDisableRelayTx(s.cfg.DisableRelayTx)
72+
73+
syncer := spv.NewSyncer(w.wallet, lp)
9274
if len(s.cfg.Peers) > 0 {
9375
dcrwLog.Debugf("Forcing SPV to peers: %s", s.cfg.Peers)
76+
syncer.SetPersistentPeers(s.cfg.Peers)
9477
}
9578

96-
err := syncer.Run(ctx)
97-
select {
98-
case <-ctx.Done():
79+
if disableDiscoverAccts {
80+
syncer.DisableDiscoverAccounts()
81+
}
82+
83+
syncer.SetNotifications(&spv.Notifications{
84+
Synced: w.onSyncerSynced,
85+
})
86+
87+
err := syncer.Run(s.runCtx)
88+
if err == nil || s.runCtx.Err() != nil {
9989
// stop() requested.
10090
return
101-
default:
102-
w.rpcSyncerFinished()
103-
dcrwLog.Errorf("SPV synchronization ended: %v", err)
10491
}
10592

93+
w.rpcSyncerFinished()
94+
dcrwLog.Errorf("SPV synchronization ended: %v", err)
95+
10696
// Backoff for 5 seconds.
10797
select {
108-
case <-ctx.Done():
98+
case <-s.runCtx.Done():
10999
// Graceful shutdown.
110100
dcrwLog.Debugf("RPCsyncer shutting down")
111101
return
@@ -119,12 +109,7 @@ func (s *SPVSyncer) start(w *DcrWallet) error {
119109

120110
func (s *SPVSyncer) stop() {
121111
dcrwLog.Debugf("SPVSyncer requested shutdown")
122-
s.mtx.Lock()
123-
if s.cancel != nil {
124-
s.cancel()
125-
s.cancel = nil
126-
}
127-
s.mtx.Unlock()
112+
s.runCancel()
128113
}
129114

130115
func (s *SPVSyncer) waitForShutdown() {

0 commit comments

Comments
 (0)