t.Errorf("expected echo of size %d; got %d", handlerN, buf.Len())
}
}
-
-// Issue 48642: close accepted connection
-func TestServerCloseAccepted(t *testing.T) {
- closed := 0
- conn := &rwTestConn{
- closeFunc: func() error {
- closed++
- return nil
- },
- }
- ln := &oneConnListener{conn: conn}
- var srv Server
- // Use ConnContext to close server after connection is accepted but before it is tracked
- srv.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
- srv.Close()
- return ctx
- }
- got := srv.Serve(ln)
- if got != ErrServerClosed {
- t.Errorf("Serve err = %v; want ErrServerClosed", got)
- }
- if closed != 1 {
- t.Errorf("Connection expected to be closed")
- }
-}
func (c *conn) setState(nc net.Conn, state ConnState, runHook bool) {
srv := c.server
switch state {
+ case StateNew:
+ srv.trackConn(c, true)
case StateHijacked, StateClosed:
- srv.mu.Lock()
- delete(srv.activeConn, c)
- srv.mu.Unlock()
+ srv.trackConn(c, false)
}
if state > 0xff || state < 0 {
panic("internal error")
}
tempDelay = 0
c := srv.newConn(rw)
- if !srv.trackConn(c) {
- rw.Close()
- return ErrServerClosed
- }
c.setState(c.rwc, StateNew, runHooks) // before Serve can return
go c.serve(connCtx)
}
return true
}
-// trackConn adds a connection to the set of tracked connections.
-// It reports whether the server is still up (not Shutdown or Closed).
-func (s *Server) trackConn(c *conn) bool {
+func (s *Server) trackConn(c *conn, add bool) {
s.mu.Lock()
defer s.mu.Unlock()
- if s.shuttingDown() {
- return false
- }
if s.activeConn == nil {
s.activeConn = make(map[*conn]struct{})
}
- s.activeConn[c] = struct{}{}
- return true
+ if add {
+ s.activeConn[c] = struct{}{}
+ } else {
+ delete(s.activeConn, c)
+ }
}
func (s *Server) idleTimeout() time.Duration {