mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-20 14:59:26 +00:00
p2p/tracker: fix crash in clean when tracker is stopped (#33940)
This commit is contained in:
parent
d318e8eba9
commit
9962e2c9f3
2 changed files with 27 additions and 3 deletions
|
|
@ -138,6 +138,10 @@ func (t *Tracker) clean() {
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
if t.expire == nil {
|
||||||
|
return // Tracker was stopped.
|
||||||
|
}
|
||||||
|
|
||||||
// Expire anything within a certain threshold (might be no items at all if
|
// Expire anything within a certain threshold (might be no items at all if
|
||||||
// we raced with the delivery)
|
// we raced with the delivery)
|
||||||
for t.expire.Len() > 0 {
|
for t.expire.Len() > 0 {
|
||||||
|
|
@ -162,14 +166,15 @@ func (t *Tracker) clean() {
|
||||||
t.schedule()
|
t.schedule()
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule starts a timer to trigger on the expiration of the first network
|
// schedule starts a timer to trigger on the expiration of the first network packet.
|
||||||
// packet.
|
|
||||||
func (t *Tracker) schedule() {
|
func (t *Tracker) schedule() {
|
||||||
if t.expire.Len() == 0 {
|
if t.expire.Len() == 0 {
|
||||||
t.wake = nil
|
t.wake = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.wake = time.AfterFunc(time.Until(t.pending[t.expire.Front().Value.(uint64)].time.Add(t.timeout)), t.clean)
|
nextID := t.expire.Front().Value.(uint64)
|
||||||
|
nextTime := t.pending[nextID].time
|
||||||
|
t.wake = time.AfterFunc(time.Until(nextTime.Add(t.timeout)), t.clean)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop reclaims resources of the tracker.
|
// Stop reclaims resources of the tracker.
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,25 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestCleanAfterStop verifies that the clean method does not crash when called
|
||||||
|
// after Stop. This can happen because clean is scheduled via time.AfterFunc and
|
||||||
|
// may fire after Stop sets t.expire to nil.
|
||||||
|
func TestCleanAfterStop(t *testing.T) {
|
||||||
|
cap := p2p.Cap{Name: "test", Version: 1}
|
||||||
|
timeout := 50 * time.Millisecond
|
||||||
|
tr := New(cap, "peer1", timeout)
|
||||||
|
|
||||||
|
// Track a request to start the expiration timer.
|
||||||
|
tr.Track(Request{ID: 1, ReqCode: 0x01, RespCode: 0x02, Size: 1})
|
||||||
|
|
||||||
|
// Stop the tracker, then wait for the timer to fire.
|
||||||
|
tr.Stop()
|
||||||
|
time.Sleep(timeout + 50*time.Millisecond)
|
||||||
|
|
||||||
|
// Also verify that calling clean directly after stop doesn't panic.
|
||||||
|
tr.clean()
|
||||||
|
}
|
||||||
|
|
||||||
// This checks that metrics gauges for pending requests are be decremented when a
|
// This checks that metrics gauges for pending requests are be decremented when a
|
||||||
// Tracker is stopped.
|
// Tracker is stopped.
|
||||||
func TestMetricsOnStop(t *testing.T) {
|
func TestMetricsOnStop(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue