github-vet / github-vet/rangeloop-pointer-findings
folbricht/routedns: pipeline.go; 95 LoC
- Dominant language
- No language data
- Stars
- 0
- Forks
- 0
- PR merge metrics
- PR metrics pending
Description
Found a possible issue in [folbricht/routedns](https://www.github.com/folbricht/routedns) at [pipeline.go](https://github.com/folbricht/routedns/blob/3f8208d4302a682264e3013e31100e5cc508769c/pipeline.go#L75-L169)
Below is the message reported by the analyzer for this snippet of code. Beware that the analyzer only reports the first
issue it finds, so please do not limit your consideration to the contents of the below message.
> range-loop variable req used in defer or goroutine at line 87
[Click here to see the code in its original context.](https://github.com/folbricht/routedns/blob/3f8208d4302a682264e3013e31100e5cc508769c/pipeline.go#L75-L169)
Click here to show the 95 line(s) of Go which triggered the analyzer.
```go
for req := range c.requests { // Lazy connection. Only open a real connection if there's a request
done := make(chan struct{})
log.Trace("opening connection")
conn, err := c.client.Dial(c.addr)
if err != nil {
c.metrics.err.Add("open", 1)
log.WithError(err).Error("failed to open connection")
req.markDone(nil, err)
continue
}
wg.Add(2)
go func() { c.requests <- req }() // re-queue the request that triggered the upstream connection
go func() { // writer
for {
select {
case req := <-c.requests:
query := inFlight.add(req)
log.WithField("qname", qName(query)).Trace("sending query")
c.metrics.query.Add(1)
if err := conn.WriteMsg(query); err != nil {
req.markDone(nil, err) // fail the request
inFlight.get(query) // clean up the in-flight queue so it doesn't keep growing
conn.Close() // throw away this connection, should wake up the reader as well
wg.Done()
c.metrics.err.Add("send_query", 1)
log.WithField("qname", qName(query)).WithError(err).Trace("failed sending query")
return
}
case <-done: // the reader ran into an error and we want to stop using this connection
wg.Done()
return
}
}
}()
go func() { // reader
for {
// Set the idle deadline on the reader, not the writer since when using UDP "connections",
// a network topology change wouldn't be noticed. Putting the idle timeout here ensures
// a reconnect in that case as well. This does create a very slight race however if the
// sender is using the connection right at the time of the timeout in the receiver.
_ = conn.SetReadDeadline(time.Now().Add(idleTimeout))
a, err := conn.ReadMsg()
if err != nil {
switch e := err.(type) {
case net.Error:
if e.Timeout() {
log.Trace("connection terminated by idle timeout")
} else {
c.metrics.err.Add("server_term", 1)
log.Trace("connection terminated by server")
}
close(done) // tell the writer to not use this connection anymore
wg.Done()
return
default:
if err == io.EOF {
c.metrics.err.Add("server_eof", 1)
log.Trace("connection terminated by server")
close(done) // tell the writer to not use this connection anymore
wg.Done()
return
}
// It's possible the response can't be correctly parsed, but we do have a response.
// In this case, return it and carry on, don't terminate the connection because we
// got a bad packet (like a truncated one for example).
if a == nil {
c.metrics.err.Add("read", 1)
log.WithError(err).Error("read failed")
close(done) // tell the writer to not use this connection anymore
wg.Done()
return
}
log.WithField("qname", qName(a)).Warn(err)
}
}
req := inFlight.get(a) // match the answer to an in-flight query
if req == nil {
c.metrics.err.Add("unexpected_a", 1)
log.WithField("qname", qName(a)).Warn("unexpected answer received, ignoring")
continue
}
c.metrics.response.Add(rCode(a), 1)
req.markDone(a, nil)
ql := inFlight.maxQueueLen()
if ql > c.metrics.maxQueueLen.Value() {
c.metrics.maxQueueLen.Set(ql)
}
}
}()
// wait for both, sender and receiver to terminate before trying to reconnect
wg.Wait()
}
```
Leave a reaction on this issue to contribute to the project by classifying this instance as a **Bug** :-1:, **Mitigated** :+1:, or **Desirable Behavior** :rocket:
See the descriptions of the classifications [here](https://github.com/github-vet/rangeclosure-findings#how-can-i-help) for more information.
commit ID: 3f8208d4302a682264e3013e31100e5cc508769c
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.