Fix graceful reload (#141)

Fix CoreDNS graceful reloading. This uses the same stuff as Caddy
(obviously), but extends it for UDP listeners as well. Also add to the
README that we *will* call Shutdown for middleware.

Fixes #4
This commit is contained in:
Miek Gieben
2016-04-28 21:15:45 +01:00
parent e34280e7af
commit a1478f891d
5 changed files with 91 additions and 130 deletions

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"io/ioutil"
"log"
"net"
"os"
"path"
"strings"
@@ -197,36 +198,52 @@ func startServers(groupings bindingGroup) error {
s.TLSConfig.GetCertificate = https.GetCertificate
}
var ln server.ListenerFile
/*
if IsRestart() {
// Look up this server's listener in the map of inherited file descriptors;
// if we don't have one, we must make a new one (later).
if fdIndex, ok := loadedGob.ListenerFds[s.Addr]; ok {
file := os.NewFile(fdIndex, "")
var (
ln net.Listener
pc net.PacketConn
)
fln, err := net.FileListener(file)
if err != nil {
return err
}
if IsRestart() {
// Look up this server's listener in the map of inherited file descriptors; if we don't have one, we must make a new one (later).
if fdIndex, ok := loadedGob.ListenerFds["tcp"+s.Addr]; ok {
file := os.NewFile(fdIndex, "")
ln, ok = fln.(server.ListenerFile)
if !ok {
return errors.New("listener for " + s.Addr + " was not a ListenerFile")
}
file.Close()
delete(loadedGob.ListenerFds, s.Addr)
fln, err := net.FileListener(file)
if err != nil {
return err
}
ln, ok = fln.(*net.TCPListener)
if !ok {
return errors.New("listener for " + s.Addr + " was not a *net.TCPListener")
}
file.Close()
delete(loadedGob.ListenerFds, "tcp"+s.Addr)
}
*/
if fdIndex, ok := loadedGob.ListenerFds["udp"+s.Addr]; ok {
file := os.NewFile(fdIndex, "")
fpc, err := net.FilePacketConn(file)
if err != nil {
return err
}
pc, ok = fpc.(*net.UDPConn)
if !ok {
return errors.New("packetConn for " + s.Addr + " was not a *net.PacketConn")
}
file.Close()
delete(loadedGob.ListenerFds, "udp"+s.Addr)
}
}
wg.Add(1)
go func(s *server.Server, ln server.ListenerFile) {
go func(s *server.Server, ln net.Listener, pc net.PacketConn) {
defer wg.Done()
// run startup functions that should only execute when
// the original parent process is starting.
// run startup functions that should only execute when the original parent process is starting.
if !IsRestart() && !startedBefore {
err := s.RunFirstStartupFuncs()
if err != nil {
@@ -236,14 +253,12 @@ func startServers(groupings bindingGroup) error {
}
// start the server
// TODO(miek): for now will always be nil, so we will run ListenAndServe()
// TODO(miek): this is also why graceful restarts don't work.
if ln != nil {
//errChan <- s.Serve(ln)
if ln != nil && pc != nil {
errChan <- s.Serve(ln, pc)
} else {
errChan <- s.ListenAndServe()
}
}(s, ln)
}(s, ln, pc)
startupWg.Add(1)
go func(s *server.Server) {

View File

@@ -81,9 +81,14 @@ func Restart(newCorefile Input) error {
// Add file descriptors of all the sockets
serversMu.Lock()
for i, s := range servers {
j := 0
for _, s := range servers {
extraFiles = append(extraFiles, s.ListenerFd())
crfileGob.ListenerFds[s.Addr] = uintptr(4 + i) // 4 fds come before any of the listeners
extraFiles = append(extraFiles, s.PacketConnFd())
// So this will be 0 1 2 3 TCP UDP TCP UDP ... etc.
crfileGob.ListenerFds["tcp"+s.Addr] = uintptr(4 + j) // 4 fds come before any of the listeners
crfileGob.ListenerFds["udp"+s.Addr] = uintptr(4 + j + 1) // add udp after that
j += 2
}
serversMu.Unlock()