whisper: fix whisper go routine leak with sync wait group (#20844)
This commit is contained in:
parent
f0be151349
commit
a5a9feab21
@ -44,6 +44,8 @@ type Peer struct {
|
|||||||
known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
|
known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
|
|
||||||
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPeer creates a new whisper peer object, but does not run the handshake itself.
|
// newPeer creates a new whisper peer object, but does not run the handshake itself.
|
||||||
@ -64,6 +66,7 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
|
|||||||
// start initiates the peer updater, periodically broadcasting the whisper packets
|
// start initiates the peer updater, periodically broadcasting the whisper packets
|
||||||
// into the network.
|
// into the network.
|
||||||
func (peer *Peer) start() {
|
func (peer *Peer) start() {
|
||||||
|
peer.wg.Add(1)
|
||||||
go peer.update()
|
go peer.update()
|
||||||
log.Trace("start", "peer", peer.ID())
|
log.Trace("start", "peer", peer.ID())
|
||||||
}
|
}
|
||||||
@ -71,6 +74,7 @@ func (peer *Peer) start() {
|
|||||||
// stop terminates the peer updater, stopping message forwarding to it.
|
// stop terminates the peer updater, stopping message forwarding to it.
|
||||||
func (peer *Peer) stop() {
|
func (peer *Peer) stop() {
|
||||||
close(peer.quit)
|
close(peer.quit)
|
||||||
|
peer.wg.Wait()
|
||||||
log.Trace("stop", "peer", peer.ID())
|
log.Trace("stop", "peer", peer.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +85,9 @@ func (peer *Peer) handshake() error {
|
|||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
isLightNode := peer.host.LightClientMode()
|
isLightNode := peer.host.LightClientMode()
|
||||||
isRestrictedLightNodeConnection := peer.host.LightClientModeConnectionRestricted()
|
isRestrictedLightNodeConnection := peer.host.LightClientModeConnectionRestricted()
|
||||||
|
peer.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer peer.wg.Done()
|
||||||
pow := peer.host.MinPow()
|
pow := peer.host.MinPow()
|
||||||
powConverted := math.Float64bits(pow)
|
powConverted := math.Float64bits(pow)
|
||||||
bloom := peer.host.BloomFilter()
|
bloom := peer.host.BloomFilter()
|
||||||
@ -144,6 +150,7 @@ func (peer *Peer) handshake() error {
|
|||||||
// update executes periodic operations on the peer, including message transmission
|
// update executes periodic operations on the peer, including message transmission
|
||||||
// and expiration.
|
// and expiration.
|
||||||
func (peer *Peer) update() {
|
func (peer *Peer) update() {
|
||||||
|
defer peer.wg.Done()
|
||||||
// Start the tickers for the updates
|
// Start the tickers for the updates
|
||||||
expire := time.NewTicker(expirationCycle)
|
expire := time.NewTicker(expirationCycle)
|
||||||
defer expire.Stop()
|
defer expire.Stop()
|
||||||
|
@ -88,6 +88,8 @@ type Whisper struct {
|
|||||||
stats Statistics // Statistics of whisper node
|
stats Statistics // Statistics of whisper node
|
||||||
|
|
||||||
mailServer MailServer // MailServer interface
|
mailServer MailServer // MailServer interface
|
||||||
|
|
||||||
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a Whisper client ready to communicate through the Ethereum P2P network.
|
// New creates a Whisper client ready to communicate through the Ethereum P2P network.
|
||||||
@ -243,8 +245,10 @@ func (whisper *Whisper) SetBloomFilter(bloom []byte) error {
|
|||||||
whisper.settings.Store(bloomFilterIdx, b)
|
whisper.settings.Store(bloomFilterIdx, b)
|
||||||
whisper.notifyPeersAboutBloomFilterChange(b)
|
whisper.notifyPeersAboutBloomFilterChange(b)
|
||||||
|
|
||||||
|
whisper.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
// allow some time before all the peers have processed the notification
|
// allow some time before all the peers have processed the notification
|
||||||
|
defer whisper.wg.Done()
|
||||||
time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
|
time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
|
||||||
whisper.settings.Store(bloomFilterToleranceIdx, b)
|
whisper.settings.Store(bloomFilterToleranceIdx, b)
|
||||||
}()
|
}()
|
||||||
@ -261,7 +265,9 @@ func (whisper *Whisper) SetMinimumPoW(val float64) error {
|
|||||||
whisper.settings.Store(minPowIdx, val)
|
whisper.settings.Store(minPowIdx, val)
|
||||||
whisper.notifyPeersAboutPowRequirementChange(val)
|
whisper.notifyPeersAboutPowRequirementChange(val)
|
||||||
|
|
||||||
|
whisper.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer whisper.wg.Done()
|
||||||
// allow some time before all the peers have processed the notification
|
// allow some time before all the peers have processed the notification
|
||||||
time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
|
time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
|
||||||
whisper.settings.Store(minPowToleranceIdx, val)
|
whisper.settings.Store(minPowToleranceIdx, val)
|
||||||
@ -626,10 +632,12 @@ func (whisper *Whisper) Send(envelope *Envelope) error {
|
|||||||
// of the Whisper protocol.
|
// of the Whisper protocol.
|
||||||
func (whisper *Whisper) Start(*p2p.Server) error {
|
func (whisper *Whisper) Start(*p2p.Server) error {
|
||||||
log.Info("started whisper v." + ProtocolVersionStr)
|
log.Info("started whisper v." + ProtocolVersionStr)
|
||||||
|
whisper.wg.Add(1)
|
||||||
go whisper.update()
|
go whisper.update()
|
||||||
|
|
||||||
numCPU := runtime.NumCPU()
|
numCPU := runtime.NumCPU()
|
||||||
for i := 0; i < numCPU; i++ {
|
for i := 0; i < numCPU; i++ {
|
||||||
|
whisper.wg.Add(1)
|
||||||
go whisper.processQueue()
|
go whisper.processQueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,6 +648,7 @@ func (whisper *Whisper) Start(*p2p.Server) error {
|
|||||||
// of the Whisper protocol.
|
// of the Whisper protocol.
|
||||||
func (whisper *Whisper) Stop() error {
|
func (whisper *Whisper) Stop() error {
|
||||||
close(whisper.quit)
|
close(whisper.quit)
|
||||||
|
whisper.wg.Wait()
|
||||||
log.Info("whisper stopped")
|
log.Info("whisper stopped")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -874,6 +883,7 @@ func (whisper *Whisper) checkOverflow() {
|
|||||||
|
|
||||||
// processQueue delivers the messages to the watchers during the lifetime of the whisper node.
|
// processQueue delivers the messages to the watchers during the lifetime of the whisper node.
|
||||||
func (whisper *Whisper) processQueue() {
|
func (whisper *Whisper) processQueue() {
|
||||||
|
defer whisper.wg.Done()
|
||||||
var e *Envelope
|
var e *Envelope
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -892,6 +902,7 @@ func (whisper *Whisper) processQueue() {
|
|||||||
// update loops until the lifetime of the whisper node, updating its internal
|
// update loops until the lifetime of the whisper node, updating its internal
|
||||||
// state by expiring stale messages from the pool.
|
// state by expiring stale messages from the pool.
|
||||||
func (whisper *Whisper) update() {
|
func (whisper *Whisper) update() {
|
||||||
|
defer whisper.wg.Done()
|
||||||
// Start a ticker to check for expirations
|
// Start a ticker to check for expirations
|
||||||
expire := time.NewTicker(expirationCycle)
|
expire := time.NewTicker(expirationCycle)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user