The default implementation of Accept, which spins up a new server
for every new connection, calls log.Fatal if the listener is closed,
stopping any outstanding work. Change that to a non-fatal log
call so work can continue.
There is no programmatic signaling of the problem, just the log,
but that should be enough.
Fixes #11221.
Change-Id: I7c7f6164a0a0143236729eb778d7638c51c34ed1
Reviewed-on: https://go-review.googlesource.com/14185
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
}
// Accept accepts connections on the listener and serves requests
-// for each incoming connection. Accept blocks; the caller typically
-// invokes it in a go statement.
+// for each incoming connection. Accept blocks until the listener
+// returns a non-nil error. The caller typically invokes Accept in a
+// go statement.
func (server *Server) Accept(lis net.Listener) {
for {
conn, err := lis.Accept()
if err != nil {
- log.Fatal("rpc.Serve: accept:", err.Error()) // TODO(r): exit?
+ log.Print("rpc.Serve: accept:", err.Error())
+ return
}
go server.ServeConn(conn)
}
}
}
+// Tests the fix to issue 11221. Without the fix, this loops forever or crashes.
+func TestAcceptExitAfterListenerClose(t *testing.T) {
+ newServer = NewServer()
+ newServer.Register(new(Arith))
+ newServer.RegisterName("net.rpc.Arith", new(Arith))
+ newServer.RegisterName("newServer.Arith", new(Arith))
+
+ var l net.Listener
+ l, newServerAddr = listenTCP()
+ l.Close()
+ newServer.Accept(l)
+}
+
func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
once.Do(startServer)
client, err := dial()