mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-26 02:09:47 +08:00
b5b31e398c
Lots of refinement still needed and runs only on POSIX systems. Windows will not get true graceful restarts (for now), but we will opt for very, very quick forceful restarts. Also, server configs are no longer put into a map; it is critical that they stay ordered so that they can be matched with their sockets in the child process after forking. This implementation of graceful restarts is probably not perfect, but it is a good start. Lots of details to attend to now.
71 lines
1.7 KiB
Go
71 lines
1.7 KiB
Go
package server
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
"sync"
|
|
"syscall"
|
|
)
|
|
|
|
// newGracefulListener returns a gracefulListener that wraps l and
|
|
// uses wg (stored in the host server) to count connections.
|
|
func newGracefulListener(l ListenerFile, wg *sync.WaitGroup) *gracefulListener {
|
|
gl := &gracefulListener{ListenerFile: l, stop: make(chan error), httpWg: wg}
|
|
go func() {
|
|
<-gl.stop
|
|
gl.stopped = true
|
|
gl.stop <- gl.ListenerFile.Close()
|
|
}()
|
|
return gl
|
|
}
|
|
|
|
// gracefuListener is a net.Listener which can
|
|
// count the number of connections on it. Its
|
|
// methods mainly wrap net.Listener to be graceful.
|
|
type gracefulListener struct {
|
|
ListenerFile
|
|
stop chan error
|
|
stopped bool
|
|
httpWg *sync.WaitGroup // pointer to the host's wg used for counting connections
|
|
}
|
|
|
|
// Accept accepts a connection. This type wraps
|
|
func (gl *gracefulListener) Accept() (c net.Conn, err error) {
|
|
c, err = gl.ListenerFile.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
c = gracefulConn{Conn: c, httpWg: gl.httpWg}
|
|
gl.httpWg.Add(1)
|
|
return
|
|
}
|
|
|
|
// Close immediately closes the listener.
|
|
func (gl *gracefulListener) Close() error {
|
|
if gl.stopped {
|
|
return syscall.EINVAL
|
|
}
|
|
gl.stop <- nil
|
|
return <-gl.stop
|
|
}
|
|
|
|
// File implements ListenerFile; it gets the file of the listening socket.
|
|
func (gl *gracefulListener) File() (*os.File, error) {
|
|
return gl.ListenerFile.File()
|
|
}
|
|
|
|
// gracefulConn represents a connection on a
|
|
// gracefulListener so that we can keep track
|
|
// of the number of connections, thus facilitating
|
|
// a graceful shutdown.
|
|
type gracefulConn struct {
|
|
net.Conn
|
|
httpWg *sync.WaitGroup // pointer to the host server's connection waitgroup
|
|
}
|
|
|
|
// Close closes c's underlying connection while updating the wg count.
|
|
func (c gracefulConn) Close() error {
|
|
c.httpWg.Done()
|
|
return c.Conn.Close()
|
|
}
|