Commit 26557579 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

http: don't fail on accept hitting EMFILE

Fixes #1891

R=rsc
CC=golang-dev
https://golang.org/cl/4550112
parent 0015e8eb
......@@ -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) {
......
......@@ -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 {
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment