diff options
| author | Brad Fitzpatrick <bradfitz@golang.org> | 2018-04-12 20:25:07 +0000 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2018-06-15 02:07:23 +0000 |
| commit | f70d1e76cc0ed2550d83fbc04356f7d2308044c4 (patch) | |
| tree | e6f5c1862f6ffa11f17a453ac4bb99063095a3cb /src/net/http/server.go | |
| parent | 8998c55ec071ae36f2d32c8852a945f032239c4c (diff) | |
| download | go-f70d1e76cc0ed2550d83fbc04356f7d2308044c4.tar.xz | |
net/http: ensure that Listener.Close is called only once in Server.Serve
Fixes #24803
Change-Id: I8b1e7c5a74018a0c333f8c38a7ec5f5827ab1606
Reviewed-on: https://go-review.googlesource.com/106715
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src/net/http/server.go')
| -rw-r--r-- | src/net/http/server.go | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/src/net/http/server.go b/src/net/http/server.go index 407546d6c9..d54b745cd2 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2770,10 +2770,13 @@ var ErrServerClosed = errors.New("http: Server closed") // Serve always returns a non-nil error. After Shutdown or Close, the // returned error is ErrServerClosed. func (srv *Server) Serve(l net.Listener) error { - defer l.Close() if fn := testHookServerServe; fn != nil { - fn(srv, l) + fn(srv, l) // call hook with unwrapped listener } + + l = &onceCloseListener{Listener: l} + defer l.Close() + var tempDelay time.Duration // how long to sleep on accept failure if err := srv.setupHTTP2_Serve(); err != nil { @@ -3249,6 +3252,21 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { return tc, nil } +// onceCloseListener wraps a net.Listener, protecting it from +// multiple Close calls. +type onceCloseListener struct { + net.Listener + once sync.Once + closeErr error +} + +func (oc *onceCloseListener) Close() error { + oc.once.Do(oc.close) + return oc.closeErr +} + +func (oc *onceCloseListener) close() { oc.closeErr = oc.Listener.Close() } + // globalOptionsHandler responds to "OPTIONS *" requests. type globalOptionsHandler struct{} |
