From d176fc029ca351b82e7d14f89a8e9a9551f2f4b6 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Mon, 18 Sep 2023 13:31:41 +0200 Subject: [PATCH] scion/ping: wait for send go routine to terminate (#4392) Wait for the ping sender go routine to terminate before we return the stats. With bad luck, the receiver go routine receives all the replies before the sender go routine has terminated. Because only the sender go routine increments the stats.Sent count, we end up with wrong stats that claim more packets were received then sent. The race condition is that `WriteTo` in the last `pinger.send` succeeds, but then the writer go-routine is not scheduled to increment the `stats.Sent` counter before these stats are returned from `pinger.Ping`. --- scion/ping/ping.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scion/ping/ping.go b/scion/ping/ping.go index c332bce42c..4efea528d5 100644 --- a/scion/ping/ping.go +++ b/scion/ping/ping.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "math/rand" "net" + "sync" "time" "github.com/scionproto/scion/pkg/addr" @@ -178,8 +179,12 @@ func (p *pinger) Ping(ctx context.Context, remote *snet.UDPAddr) (Stats, error) p.drain(ctx) }() + var wg sync.WaitGroup + wg.Add(1) + go func() { defer log.HandlePanic() + defer wg.Done() for i := uint16(0); i < p.attempts; i++ { if err := p.send(remote); err != nil { errSend <- serrors.WrapStr("sending", err) @@ -210,6 +215,7 @@ func (p *pinger) Ping(ctx context.Context, remote *snet.UDPAddr) (Stats, error) p.receive(reply) } } + wg.Wait() return p.stats, nil }