Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/http: bug in late binding #10155

Closed
dvyukov opened this issue Mar 13, 2015 · 1 comment

Comments

Projects
None yet
4 participants
@dvyukov
Copy link
Member

commented Mar 13, 2015

Late binding does the following (putIdleConn):

waitingDialer := t.idleConnCh[key]
select {
case waitingDialer <- pconn:
    t.idleMu.Unlock()
    return true
default:
    if waitingDialer != nil {
        delete(t.idleConnCh, key)
    }
}

However, receive in getConn is not atomic with creation of the idleConnCh channel, so it is possible that:

  • getConn inserts a chan into idleConnCh
  • putIdleConn gets the chan, but the non-blocking send fails
  • getConn blocks on receive from idleConnCh

So when we need a conn the most, we actually miss the opportunity to match getConn and putIdleConn.

Another bad consequence is that putIdleConn will delete the chan from t.idleConnCh in this situation. This can disable late binding for a set of concurrent getConn's -- subsequent putIdleConn's won't hand off connections to them.

@bradfitz

@rsc rsc added this to the Go1.5 milestone Apr 10, 2015

@bradfitz

This comment has been minimized.

Copy link
Member

commented Apr 30, 2015

This whole mechanism is best effort anyway, so I don't think this is a big deal. The logical race (not a data race) window is very small, and subsequent getConn calls will restore any channel that is deleted too early. The network round-trip time is so much larger than the goroutine scheduling time between locking a mutex, doing a map lookup, unlocking a mutex, and doing a receive-or-default-out unbuffered channel read.

I looked into this, but I think any fix would be more gross and invasive than it would be beneficial.

I'd rather not fix this, so I'm going to close it. If you have a minimal fix, I'd be open to looking at it, but I'd rather focus my time on HTTP/2 stuff right now.

@bradfitz bradfitz closed this Apr 30, 2015

@golang golang locked and limited conversation to collaborators Jun 25, 2016

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.