aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelföldi Zsolt <zsfelfoldi@gmail.com>2019-05-18 02:39:39 +0800
committerGitHub <noreply@github.com>2019-05-18 02:39:39 +0800
commit97d3615612a49488d02807944696d001b88f9e0d (patch)
tree4c01b43bbabb7a773807876b6bc0d6d9bfcfc57c
parente687d063c360a78786e021f5ada935ef643e3815 (diff)
downloadgo-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar.gz
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar.bz2
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar.lz
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar.xz
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.tar.zst
go-tangerine-97d3615612a49488d02807944696d001b88f9e0d.zip
les: avoid fetcher deadlock on requestChn (#19571)
* les: avoid fetcher deadlock on requestChn
-rw-r--r--les/fetcher.go29
1 files changed, 14 insertions, 15 deletions
diff --git a/les/fetcher.go b/les/fetcher.go
index 057552f53..fa02be9a2 100644
--- a/les/fetcher.go
+++ b/les/fetcher.go
@@ -55,7 +55,8 @@ type lightFetcher struct {
requested map[uint64]fetchRequest
deliverChn chan fetchResponse
timeoutChn chan uint64
- requestChn chan bool // true if initiated from outside
+ requestTriggered bool
+ requestTrigger chan struct{}
lastTrustedHeader *types.Header
}
@@ -122,7 +123,7 @@ func newLightFetcher(pm *ProtocolManager) *lightFetcher {
deliverChn: make(chan fetchResponse, 100),
requested: make(map[uint64]fetchRequest),
timeoutChn: make(chan uint64),
- requestChn: make(chan bool, 100),
+ requestTrigger: make(chan struct{}, 1),
syncDone: make(chan *peer),
maxConfirmedTd: big.NewInt(0),
}
@@ -135,31 +136,26 @@ func newLightFetcher(pm *ProtocolManager) *lightFetcher {
// syncLoop is the main event loop of the light fetcher
func (f *lightFetcher) syncLoop() {
- requesting := false
defer f.pm.wg.Done()
for {
select {
case <-f.pm.quitSync:
return
- // when a new announce is received, request loop keeps running until
- // no further requests are necessary or possible
- case newAnnounce := <-f.requestChn:
+ // request loop keeps running until no further requests are necessary or possible
+ case <-f.requestTrigger:
f.lock.Lock()
- s := requesting
- requesting = false
var (
rq *distReq
reqID uint64
syncing bool
)
-
- if !f.syncing && !(newAnnounce && s) {
+ if !f.syncing {
rq, reqID, syncing = f.nextRequest()
}
+ f.requestTriggered = rq != nil
f.lock.Unlock()
if rq != nil {
- requesting = true
if _, ok := <-f.pm.reqDist.queue(rq); ok {
if syncing {
f.lock.Lock()
@@ -176,11 +172,11 @@ func (f *lightFetcher) syncLoop() {
}
f.reqMu.Unlock()
// keep starting new requests while possible
- f.requestChn <- false
+ f.requestTrigger <- struct{}{}
}()
}
} else {
- f.requestChn <- false
+ f.requestTrigger <- struct{}{}
}
}
case reqID := <-f.timeoutChn:
@@ -220,7 +216,7 @@ func (f *lightFetcher) syncLoop() {
f.checkSyncedHeaders(p)
f.syncing = false
f.lock.Unlock()
- f.requestChn <- false
+ f.requestTrigger <- struct{}{} // f.requestTriggered is always true here
}
}
}
@@ -354,7 +350,10 @@ func (f *lightFetcher) announce(p *peer, head *announceData) {
fp.lastAnnounced = n
p.lock.Unlock()
f.checkUpdateStats(p, nil)
- f.requestChn <- true
+ if !f.requestTriggered {
+ f.requestTriggered = true
+ f.requestTrigger <- struct{}{}
+ }
}
// peerHasBlock returns true if we can assume the peer knows the given block