Skip to content

Commit 09962cc

Browse files
committed
add timeout for stopping p2p server
1 parent ec8d46e commit 09962cc

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

eth/peerset.go

+34-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"errors"
2121
"math/big"
2222
"sync"
23+
"time"
2324

2425
"github.com/ethereum/go-ethereum/common"
2526
"github.com/ethereum/go-ethereum/eth/downloader"
@@ -38,6 +39,9 @@ var (
3839
// to the peer set, but one with the same id already exists.
3940
errPeerAlreadyRegistered = errors.New("peer already registered")
4041

42+
// errPeerWaitTimeout is returned if a peer waits extension for too long
43+
errPeerWaitTimeout = errors.New("peer wait timeout")
44+
4145
// errPeerNotRegistered is returned if a peer is attempted to be removed from
4246
// a peer set, but no peer with the given id exists.
4347
errPeerNotRegistered = errors.New("peer not registered")
@@ -51,6 +55,12 @@ var (
5155
errDiffWithoutEth = errors.New("peer connected on diff without compatible eth support")
5256
)
5357

58+
const (
59+
// extensionWaitTimeout is the maximum allowed time for the extension wait to
60+
// complete before dropping the connection.= as malicious.
61+
extensionWaitTimeout = 5 * time.Second
62+
)
63+
5464
// peerSet represents the collection of active peers currently participating in
5565
// the `eth` protocol, with or without the `snap` extension.
5666
type peerSet struct {
@@ -169,7 +179,18 @@ func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
169179
ps.snapWait[id] = wait
170180
ps.lock.Unlock()
171181

172-
return <-wait, nil
182+
select {
183+
case peer := <-wait:
184+
return peer, nil
185+
186+
case <-time.After(extensionWaitTimeout):
187+
ps.lock.Lock()
188+
if _, ok := ps.snapWait[id]; ok {
189+
delete(ps.snapWait, id)
190+
}
191+
ps.lock.Unlock()
192+
return nil, errPeerWaitTimeout
193+
}
173194
}
174195

175196
// waitDiffExtension blocks until all satellite protocols are connected and tracked
@@ -203,7 +224,18 @@ func (ps *peerSet) waitDiffExtension(peer *eth.Peer) (*diff.Peer, error) {
203224
ps.diffWait[id] = wait
204225
ps.lock.Unlock()
205226

206-
return <-wait, nil
227+
select {
228+
case peer := <-wait:
229+
return peer, nil
230+
231+
case <-time.After(extensionWaitTimeout):
232+
ps.lock.Lock()
233+
if _, ok := ps.diffWait[id]; ok {
234+
delete(ps.diffWait, id)
235+
}
236+
ps.lock.Unlock()
237+
return nil, errPeerWaitTimeout
238+
}
207239
}
208240

209241
func (ps *peerSet) GetDiffPeer(pid string) downloader.IDiffPeer {

p2p/server.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ const (
6363

6464
// Maximum amount of time allowed for writing a complete message.
6565
frameWriteTimeout = 20 * time.Second
66+
67+
// Maximum time to wait before stop the p2p server
68+
stopTimeout = 5 * time.Second
6669
)
6770

6871
var errServerStopped = errors.New("server stopped")
@@ -403,7 +406,20 @@ func (srv *Server) Stop() {
403406
}
404407
close(srv.quit)
405408
srv.lock.Unlock()
406-
srv.loopWG.Wait()
409+
410+
stopChan := make(chan struct{})
411+
defer close(stopChan)
412+
413+
go func() {
414+
srv.loopWG.Wait()
415+
stopChan <- struct{}{}
416+
}()
417+
418+
select {
419+
case <-stopChan:
420+
case <-time.After(stopTimeout):
421+
log.Warn("stop p2p server timeout, forcing stop")
422+
}
407423
}
408424

409425
// sharedUDPConn implements a shared connection. Write sends messages to the underlying connection while read returns

0 commit comments

Comments
 (0)