Skip to content

net/http: CloseNotifier fails to fire when underlying connection is gone #13165

@yichengq

Description

@yichengq

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?

/cc @jonboulle @xiang90 @eyakubovich @bdarnell @philips

from etcd-io/etcd#2468 (comment)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions