]> Cypherpunks repositories - gostls13.git/commitdiff
http: don't fail on accept hitting EMFILE
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 3 Jun 2011 19:23:50 +0000 (12:23 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 3 Jun 2011 19:23:50 +0000 (12:23 -0700)
Fixes #1891

R=rsc
CC=golang-dev
https://golang.org/cl/4550112

src/pkg/http/serve_test.go
src/pkg/http/server.go
src/pkg/os/error_posix.go

index c923c8a76d0fc167530afcc150cef8d45dc3751f..1054d4797ca9d66865cdc62a7aceb76c040013c1 100644 (file)
@@ -18,6 +18,7 @@ import (
        "net"
        "reflect"
        "strings"
+       "syscall"
        "testing"
        "time"
 )
@@ -773,6 +774,42 @@ func TestHandlerPanic(t *testing.T) {
        }
 }
 
+type errorListener struct {
+       errs []os.Error
+}
+
+func (l *errorListener) Accept() (c net.Conn, err os.Error) {
+       if len(l.errs) == 0 {
+               return nil, os.EOF
+       }
+       err = l.errs[0]
+       l.errs = l.errs[1:]
+       return
+}
+
+func (l *errorListener) Close() os.Error {
+       return nil
+}
+
+func (l *errorListener) Addr() net.Addr {
+       return dummyAddr("test-address")
+}
+
+func TestAcceptMaxFds(t *testing.T) {
+       log.SetOutput(ioutil.Discard) // is noisy otherwise
+       defer log.SetOutput(os.Stderr)
+
+       ln := &errorListener{[]os.Error{
+               &net.OpError{
+                       Op:    "accept",
+                       Error: os.Errno(syscall.EMFILE),
+               }}}
+       err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
+       if err != os.EOF {
+               t.Errorf("got error %v, want EOF", err)
+       }
+}
+
 func BenchmarkClientServer(b *testing.B) {
        b.StopTimer()
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
index 93d9d2ff4f4015cec2f41541569b6b70f88f8e4c..4063fad224cf07b513d4e59c2f5a138fd7d410d7 100644 (file)
@@ -860,6 +860,10 @@ func (srv *Server) Serve(l net.Listener) os.Error {
        for {
                rw, e := l.Accept()
                if e != nil {
+                       if ne, ok := e.(net.Error); ok && ne.Temporary() {
+                               log.Printf("http: Accept error: %v", e)
+                               continue
+                       }
                        return e
                }
                if srv.ReadTimeout != 0 {
index 0ee34e4b0eff849da8248ae106937acce61f8b2c..d43f1786d373fe2b0041d560702c61a686e0ea7e 100644 (file)
@@ -13,7 +13,7 @@ type Errno int64
 func (e Errno) String() string { return syscall.Errstr(int(e)) }
 
 func (e Errno) Temporary() bool {
-       return e == Errno(syscall.EINTR) || e.Timeout()
+       return e == Errno(syscall.EINTR) || e == Errno(syscall.EMFILE) || e.Timeout()
 }
 
 func (e Errno) Timeout() bool {