2015-05-27 15:46:45 +00:00
|
|
|
package grace
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type graceListener struct {
|
|
|
|
net.Listener
|
|
|
|
stop chan error
|
|
|
|
stopped bool
|
2015-09-10 08:35:40 +00:00
|
|
|
server *Server
|
2015-05-27 15:46:45 +00:00
|
|
|
}
|
|
|
|
|
2015-09-10 08:35:40 +00:00
|
|
|
func newGraceListener(l net.Listener, srv *Server) (el *graceListener) {
|
2015-05-27 15:46:45 +00:00
|
|
|
el = &graceListener{
|
|
|
|
Listener: l,
|
|
|
|
stop: make(chan error),
|
|
|
|
server: srv,
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
_ = <-el.stop
|
|
|
|
el.stopped = true
|
|
|
|
el.stop <- el.Listener.Close()
|
|
|
|
}()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gl *graceListener) Accept() (c net.Conn, err error) {
|
|
|
|
tc, err := gl.Listener.(*net.TCPListener).AcceptTCP()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
tc.SetKeepAlive(true)
|
|
|
|
tc.SetKeepAlivePeriod(3 * time.Minute)
|
|
|
|
|
|
|
|
c = graceConn{
|
|
|
|
Conn: tc,
|
|
|
|
server: gl.server,
|
|
|
|
}
|
|
|
|
|
|
|
|
gl.server.wg.Add(1)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-09-10 08:35:40 +00:00
|
|
|
func (gl *graceListener) Close() error {
|
|
|
|
if gl.stopped {
|
2015-05-27 15:46:45 +00:00
|
|
|
return syscall.EINVAL
|
|
|
|
}
|
2015-09-10 08:35:40 +00:00
|
|
|
gl.stop <- nil
|
|
|
|
return <-gl.stop
|
2015-05-27 15:46:45 +00:00
|
|
|
}
|
|
|
|
|
2015-09-10 08:35:40 +00:00
|
|
|
func (gl *graceListener) File() *os.File {
|
2015-05-27 15:46:45 +00:00
|
|
|
// returns a dup(2) - FD_CLOEXEC flag *not* set
|
2015-09-10 08:35:40 +00:00
|
|
|
tl := gl.Listener.(*net.TCPListener)
|
2015-05-27 15:46:45 +00:00
|
|
|
fl, _ := tl.File()
|
|
|
|
return fl
|
|
|
|
}
|