-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
I observed some odd behavior when using http.CloseNotifier on ReponseWriter in ServeHTTP.
The server program is:
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
cn, ok := w.(http.CloseNotifier)
if !ok {
log.Fatal("don't support CloseNotifier")
}
<-cn.CloseNotify()
log.Printf("CloseNotifier is fired!")
})
http.ListenAndServe(":8080", nil)
}
I compiled it using Go 1.5, and ran it on Linux version 3.13.0-48-generic (buildd@orlo) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015
.
It works when I am doing this:
$ ubuntu@ip-172-31-28-238:~$ nc 172.31.28.238 8080
GET / HTTP/1.1
^C
The CloseNotifier is fired as expected.
But it doesn't work when I am doing something like this:
$ ubuntu@ip-172-31-28-238:~$ nc 172.31.28.238 8080
GET / HTTP/1.1
GET / HTTP/1.1
^C
The server keeps a TCP connection at CLOSE_WAIT status, and client leaves a TCP connection at FIN_WAIT2
status. After several minutes, the client TCP connections disappears from Active Internet connections
in netstat
. After waiting several minutes more, TCP connection at server side becomes can't identify protocol
through lsof
. That generally means that the underlying socket is CLOSED
status but not be closed(https://idea.popcount.org/2012-12-09-lsof-cant-identify-protocol/). In all the time, CloseNotifier is not fired.
The client behavior is simulated from http-pipelining client of python urllib3 described in http://www.projectclearwater.org/adventures-in-debugging-etcd-http-pipelining-and-file-descriptor-leaks/
Any thoughts about this behavior? Is this a bug?