Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
net/http: tls handshake EOF on new connections when passing connection between goroutines #10685
When using SSL and websockets (using either gorilla or golang.org's websocket lib), moderate connection load will result in clients not connecting properly, and this message:
This doesn't happen in my basic example (located here: https://github.com/bbangert/ssl-ram-testing/blob/master/Go/golang.org/main.go) when it uses io.Copy to implement the echo server, but when it merely uses another goroutine to write the echo'd data back then the TLS handshake errors pop up.
I observed this using the latest Go 1.4.2, we have observed it in prior versions of Go in production, but this is the first time I have a minimal example of it (for testing SSL RAM overhead per connection, which is very very high in Golang, but that's a separate issue....).
The Go file I linked to has both types of echo in it, the default build of it will exhibit the EOF issue, passing the environ var "USE_COPY=true" will run the other echo handler using io.Copy that does not exhibit the EOF.
README for the Go code: https://github.com/bbangert/ssl-ram-testing/tree/master/Go/golang.org
To run the client tester, the directions are here: https://github.com/bbangert/ssl-ram-testing
You will need to increase the open file descriptors for the shell running the testing client and the Go binary as it attaches 1000 clients:
Then run the the Go code in its directory with: USE_SSL=true ./run
I'm updating the title to reflect the least common denominator. Since this is reproducible using both gorilla's websocket library and code.google.com/p/go.net/websocket, it doesn't make sense to say that its an error in the websocket library.
They both use the net/http library however, and the behavior that is occurring is a direct result of when a goroutine besides the one initially spawned to handle the request utilizes the connection object to write to it. I have tried several other variants to try and rule out race conditions, ie, I tweaked it to use the channel in lock-step to prevent read/write at once:
That doesn't help. However, if I have the new goroutine not write the data out, and instead it just passes it back, and the original goroutine handling the request does the write, no more TLS handshake problems.
My only theory at this point is that the connection has somehow mangled things in the system somewhere on being passed between the goroutine's, such that new clients get TLS handshake errors.
I just compiled Go tip, the TLS handshake errors are gone. Anyone using websockets (whether golang.org/net/websocket or gorilla) should be aware that prior to recent Go, using a connection from two goroutines will cause bad things to happen.
I was about to hit Comment on this, when I saw that the CPU usage had skyrocketed for the basic little websocket server, even though I dropped all the connections (and memory use climbed rapidly, about 150 MB of memory every 5 seconds, so I killed it quickly). So something still seems to be wrong in some way.
Any other versions of Go I should test this with?