mirror of
https://github.com/go-ping/ping.git
synced 2025-06-28 06:56:55 +00:00
Protect stats with RWMutex (#151)
* Protect stats with RWMutex updateStats() now also updates rtts so it is protected by the lock. Statistics() should now be callable from other goroutines. PacketsSent and PacketsRecvDuplicates can still be updated while Statistics() is running, and thus could yield strange results (sent<recv) To fix this, atomics could be used, but it would require changing the types of the fields from int to int64, thus changing the public api. Signed-off-by: Jean Raby <jean@raby.sh>
This commit is contained in:
parent
5f9dd908cc
commit
d90f3778a8
18
ping.go
18
ping.go
@ -143,6 +143,7 @@ type Pinger struct {
|
||||
avgRtt time.Duration
|
||||
stdDevRtt time.Duration
|
||||
stddevm2 time.Duration
|
||||
statsMu sync.RWMutex
|
||||
|
||||
// If true, keep a record of rtts of all received packets.
|
||||
// Set to false to avoid memory bloat for long running pings.
|
||||
@ -255,7 +256,14 @@ type Statistics struct {
|
||||
}
|
||||
|
||||
func (p *Pinger) updateStatistics(pkt *Packet) {
|
||||
p.statsMu.Lock()
|
||||
defer p.statsMu.Unlock()
|
||||
|
||||
p.PacketsRecv++
|
||||
if p.RecordRtts {
|
||||
p.rtts = append(p.rtts, pkt.Rtt)
|
||||
}
|
||||
|
||||
if p.PacketsRecv == 1 || pkt.Rtt < p.minRtt {
|
||||
p.minRtt = pkt.Rtt
|
||||
}
|
||||
@ -451,9 +459,12 @@ func (p *Pinger) finish() {
|
||||
// pinger is running or after it is finished. OnFinish calls this function to
|
||||
// get it's finished statistics.
|
||||
func (p *Pinger) Statistics() *Statistics {
|
||||
loss := float64(p.PacketsSent-p.PacketsRecv) / float64(p.PacketsSent) * 100
|
||||
p.statsMu.RLock()
|
||||
defer p.statsMu.RUnlock()
|
||||
sent := p.PacketsSent
|
||||
loss := float64(sent-p.PacketsRecv) / float64(sent) * 100
|
||||
s := Statistics{
|
||||
PacketsSent: p.PacketsSent,
|
||||
PacketsSent: sent,
|
||||
PacketsRecv: p.PacketsRecv,
|
||||
PacketsRecvDuplicates: p.PacketsRecvDuplicates,
|
||||
PacketLoss: loss,
|
||||
@ -582,9 +593,6 @@ func (p *Pinger) processPacket(recv *packet) error {
|
||||
return fmt.Errorf("invalid ICMP echo reply; type: '%T', '%v'", pkt, pkt)
|
||||
}
|
||||
|
||||
if p.RecordRtts {
|
||||
p.rtts = append(p.rtts, inPkt.Rtt)
|
||||
}
|
||||
handler := p.OnRecv
|
||||
if handler != nil {
|
||||
handler(inPkt)
|
||||
|
Loading…
Reference in New Issue
Block a user