fix race by sending signal instead of stopping pongTimer
This commit is contained in:
parent
26419fba28
commit
45750e1b29
|
@ -89,7 +89,7 @@ type MConnection struct {
|
||||||
|
|
||||||
// close conn if pong is not received in pongTimeout
|
// close conn if pong is not received in pongTimeout
|
||||||
pongTimer *time.Timer
|
pongTimer *time.Timer
|
||||||
pongTimeoutCh chan struct{}
|
pongTimeoutCh chan bool // true - timeout, false - peer sent pong
|
||||||
|
|
||||||
chStatsTimer *cmn.RepeatTimer // update channel stats periodically
|
chStatsTimer *cmn.RepeatTimer // update channel stats periodically
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func (c *MConnection) OnStart() error {
|
||||||
c.quit = make(chan struct{})
|
c.quit = make(chan struct{})
|
||||||
c.flushTimer = cmn.NewThrottleTimer("flush", c.config.FlushThrottle)
|
c.flushTimer = cmn.NewThrottleTimer("flush", c.config.FlushThrottle)
|
||||||
c.pingTimer = cmn.NewRepeatTimer("ping", c.config.PingInterval)
|
c.pingTimer = cmn.NewRepeatTimer("ping", c.config.PingInterval)
|
||||||
c.pongTimeoutCh = make(chan struct{})
|
c.pongTimeoutCh = make(chan bool)
|
||||||
c.chStatsTimer = cmn.NewRepeatTimer("chStats", updateStats)
|
c.chStatsTimer = cmn.NewRepeatTimer("chStats", updateStats)
|
||||||
go c.sendRoutine()
|
go c.sendRoutine()
|
||||||
go c.recvRoutine()
|
go c.recvRoutine()
|
||||||
|
@ -339,19 +339,22 @@ FOR_LOOP:
|
||||||
c.sendMonitor.Update(int(n))
|
c.sendMonitor.Update(int(n))
|
||||||
c.Logger.Debug("Starting pong timer", "dur", c.config.PongTimeout)
|
c.Logger.Debug("Starting pong timer", "dur", c.config.PongTimeout)
|
||||||
c.pongTimer = time.AfterFunc(c.config.PongTimeout, func() {
|
c.pongTimer = time.AfterFunc(c.config.PongTimeout, func() {
|
||||||
c.pongTimeoutCh <- struct{}{}
|
c.pongTimeoutCh <- true
|
||||||
})
|
})
|
||||||
c.flush()
|
c.flush()
|
||||||
case <-c.pongTimeoutCh:
|
case timeout := <-c.pongTimeoutCh:
|
||||||
c.Logger.Debug("Pong timeout")
|
if timeout {
|
||||||
err = errors.New("pong timeout")
|
c.Logger.Debug("Pong timeout")
|
||||||
|
err = errors.New("pong timeout")
|
||||||
|
} else {
|
||||||
|
c.stopPongTimer()
|
||||||
|
}
|
||||||
case <-c.pong:
|
case <-c.pong:
|
||||||
c.Logger.Debug("Send Pong")
|
c.Logger.Debug("Send Pong")
|
||||||
wire.WriteByte(packetTypePong, c.bufWriter, &n, &err)
|
wire.WriteByte(packetTypePong, c.bufWriter, &n, &err)
|
||||||
c.sendMonitor.Update(int(n))
|
c.sendMonitor.Update(int(n))
|
||||||
c.flush()
|
c.flush()
|
||||||
case <-c.quit:
|
case <-c.quit:
|
||||||
c.stopPongTimer()
|
|
||||||
break FOR_LOOP
|
break FOR_LOOP
|
||||||
case <-c.send:
|
case <-c.send:
|
||||||
// Send some msgPackets
|
// Send some msgPackets
|
||||||
|
@ -376,6 +379,7 @@ FOR_LOOP:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
c.stopPongTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if messages from channels were exhausted.
|
// Returns true if messages from channels were exhausted.
|
||||||
|
@ -486,7 +490,11 @@ FOR_LOOP:
|
||||||
}
|
}
|
||||||
case packetTypePong:
|
case packetTypePong:
|
||||||
c.Logger.Debug("Receive Pong")
|
c.Logger.Debug("Receive Pong")
|
||||||
c.stopPongTimer()
|
select {
|
||||||
|
case c.pongTimeoutCh <- false:
|
||||||
|
case <-c.quit:
|
||||||
|
break FOR_LOOP
|
||||||
|
}
|
||||||
case packetTypeMsg:
|
case packetTypeMsg:
|
||||||
pkt, n, err := msgPacket{}, int(0), error(nil)
|
pkt, n, err := msgPacket{}, int(0), error(nil)
|
||||||
wire.ReadBinaryPtr(&pkt, c.bufReader, c.config.maxMsgPacketTotalSize(), &n, &err)
|
wire.ReadBinaryPtr(&pkt, c.bufReader, c.config.maxMsgPacketTotalSize(), &n, &err)
|
||||||
|
@ -534,12 +542,14 @@ FOR_LOOP:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not goroutine-safe
|
||||||
func (c *MConnection) stopPongTimer() {
|
func (c *MConnection) stopPongTimer() {
|
||||||
if c.pongTimer != nil {
|
if c.pongTimer != nil {
|
||||||
if !c.pongTimer.Stop() {
|
if !c.pongTimer.Stop() {
|
||||||
<-c.pongTimer.C
|
<-c.pongTimer.C
|
||||||
}
|
}
|
||||||
drain(c.pongTimeoutCh)
|
drain(c.pongTimeoutCh)
|
||||||
|
c.pongTimer = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +781,7 @@ func (p msgPacket) String() string {
|
||||||
return fmt.Sprintf("MsgPacket{%X:%X T:%X}", p.ChannelID, p.Bytes, p.EOF)
|
return fmt.Sprintf("MsgPacket{%X:%X T:%X}", p.ChannelID, p.Bytes, p.EOF)
|
||||||
}
|
}
|
||||||
|
|
||||||
func drain(ch <-chan struct{}) {
|
func drain(ch <-chan bool) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ch:
|
case <-ch:
|
||||||
|
|
Loading…
Reference in New Issue