-
- mutex := &sync.RWMutex{}
- srv.cond = sync.NewCond(mutex.RLocker())
- go func() {
- err = srv.Serve(tcpKeepAliveListener{srv.listener})
- if !srv.wantDown {
- srv.err = err
- }
- mutex.Lock()
- srv.done = true
- srv.cond.Broadcast()
- mutex.Unlock()
- }()
- return nil
-}
-
-// Wait returns when the server has shut down.
-func (srv *server) Wait() error {
- srv.cond.L.Lock()
- defer srv.cond.L.Unlock()
- for !srv.done {
- srv.cond.Wait()
- }
- return srv.err
-}
-
-// Close shuts down the server and returns when it has stopped.
-func (srv *server) Close() error {
- srv.wantDown = true
- srv.listener.Close()
- return srv.Wait()
-}
-
-// tcpKeepAliveListener is copied from net/http because not exported.
-//
-type tcpKeepAliveListener struct {
- *net.TCPListener
-}
-
-func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
- tc, err := ln.AcceptTCP()
- if err != nil {
- return
- }
- tc.SetKeepAlive(true)
- tc.SetKeepAlivePeriod(3 * time.Minute)
- return tc, nil