diff options
| author | Adam Langley <agl@golang.org> | 2016-09-14 11:50:36 -0700 |
|---|---|---|
| committer | Adam Langley <agl@golang.org> | 2016-09-22 18:36:58 +0000 |
| commit | 254169d7bb6f96409ba4b405c80d28deefdb000b (patch) | |
| tree | b87d95260ad8ae6494943ea1e6a282bc8f028fe4 /src/plugin/plugin_stubs.go | |
| parent | ad5d91c17a3c0bc4acf9e4036b050517972432f0 (diff) | |
| download | go-254169d7bb6f96409ba4b405c80d28deefdb000b.tar.xz | |
crypto/tls: fix deadlock when racing to complete handshake.
After renegotiation support was added (af125a5193c) it's possible for a
Write to block on a Read when racing to complete the handshake:
1. The Write determines that a handshake is needed and tries to
take the neccesary locks in the correct order.
2. The Read also determines that a handshake is needed and wins
the race to take the locks.
3. The Read goroutine completes the handshake and wins a race
to unlock and relock c.in, which it'll hold when waiting for
more network data.
If the application-level protocol requires the Write to complete before
data can be read then the system as a whole will deadlock.
Unfortunately it doesn't appear possible to reverse the locking order of
c.in and handshakeMutex because we might read a renegotiation request at
any point and need to be able to do a handshake without unlocking.
So this change adds a sync.Cond that indicates that a goroutine has
committed to doing a handshake. Other interested goroutines can wait on
that Cond when needed.
The test for this isn't great. I was able to reproduce the deadlock with
it only when building with -race. (Because -race happened to alter the
timing just enough.)
Fixes #17101.
Change-Id: I4e8757f7b82a84e46c9963a977d089f0fb675495
Reviewed-on: https://go-review.googlesource.com/29164
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/plugin/plugin_stubs.go')
0 files changed, 0 insertions, 0 deletions
