From 821c0fab0996cbc7d8beaecd9abab4736215259a Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 26 Oct 2015 16:49:05 -0600 Subject: [PATCH] core: Refactoring POSIX-only code for build tags --- caddy/helpers.go | 63 ++++++++++++++++++---------------------- caddy/restart.go | 43 ++------------------------- caddy/restart_windows.go | 25 ++++++++++++++++ caddy/sigtrap.go | 33 +++++++++++++++++++++ caddy/sigtrap_posix.go | 26 +++++++++++++++++ 5 files changed, 114 insertions(+), 76 deletions(-) create mode 100644 caddy/restart_windows.go create mode 100644 caddy/sigtrap.go create mode 100644 caddy/sigtrap_posix.go diff --git a/caddy/helpers.go b/caddy/helpers.go index 209eb7f82..c30d7c168 100644 --- a/caddy/helpers.go +++ b/caddy/helpers.go @@ -3,52 +3,17 @@ package caddy import ( "bytes" "fmt" - "log" "os" "os/exec" - "os/signal" "runtime" "strconv" "strings" - "syscall" "github.com/mholt/caddy/caddy/letsencrypt" - "github.com/mholt/caddy/server" ) func init() { letsencrypt.OnRenew = func() error { return Restart(nil) } - - // Trap signals - go func() { - shutdown, reload := make(chan os.Signal, 1), make(chan os.Signal, 1) - signal.Notify(shutdown, os.Interrupt, os.Kill) // quit the process - signal.Notify(reload, syscall.SIGUSR1) // reload configuration - - for { - select { - case <-shutdown: - var exitCode int - - serversMu.Lock() - errs := server.ShutdownCallbacks(servers) - serversMu.Unlock() - if len(errs) > 0 { - for _, err := range errs { - log.Println(err) - } - exitCode = 1 - } - os.Exit(exitCode) - - case <-reload: - err := Restart(nil) - if err != nil { - log.Println(err) - } - } - } - }() } // isLocalhost returns true if the string looks explicitly like a localhost address. @@ -72,3 +37,31 @@ func checkFdlimit() { } } } + +// caddyfileGob maps bind address to index of the file descriptor +// in the Files array passed to the child process. It also contains +// the caddyfile contents. Used only during graceful restarts. +type caddyfileGob struct { + ListenerFds map[string]uintptr + Caddyfile []byte +} + +// isRestart returns whether this process is, according +// to env variables, a fork as part of a graceful restart. +func isRestart() bool { + return os.Getenv("CADDY_RESTART") == "true" +} + +// CaddyfileInput represents a Caddyfile as input +// and is simply a convenient way to implement +// the Input interface. +type CaddyfileInput struct { + Filepath string + Contents []byte +} + +// Body returns c.Contents. +func (c CaddyfileInput) Body() []byte { return c.Contents } + +// Path returns c.Filepath. +func (c CaddyfileInput) Path() string { return c.Filepath } diff --git a/caddy/restart.go b/caddy/restart.go index 43848bf62..7a07fbc1b 100644 --- a/caddy/restart.go +++ b/caddy/restart.go @@ -1,3 +1,5 @@ +// +build !windows + package caddy import ( @@ -5,18 +7,9 @@ import ( "io/ioutil" "log" "os" - "runtime" "syscall" ) -// caddyfileGob maps bind address to index of the file descriptor -// in the Files array passed to the child process. It also contains -// the caddyfile contents. Used only during graceful restarts. -type caddyfileGob struct { - ListenerFds map[string]uintptr - Caddyfile []byte -} - // Restart restarts the entire application; gracefully with zero // downtime if on a POSIX-compatible system, or forcefully if on // Windows but with imperceptibly-short downtime. @@ -31,18 +24,6 @@ func Restart(newCaddyfile Input) error { caddyfileMu.Unlock() } - if runtime.GOOS == "windows" { - err := Stop() - if err != nil { - return err - } - err = Start(newCaddyfile) - if err != nil { - return err - } - return nil - } - if len(os.Args) == 0 { // this should never happen, but just in case... os.Args = []string{""} } @@ -110,23 +91,3 @@ func Restart(newCaddyfile Input) error { // Child process is listening now; we can stop all our servers here. return Stop() } - -// isRestart returns whether this process is, according -// to env variables, a fork as part of a graceful restart. -func isRestart() bool { - return os.Getenv("CADDY_RESTART") == "true" -} - -// CaddyfileInput represents a Caddyfile as input -// and is simply a convenient way to implement -// the Input interface. -type CaddyfileInput struct { - Filepath string - Contents []byte -} - -// Body returns c.Contents. -func (c CaddyfileInput) Body() []byte { return c.Contents } - -// Path returns c.Filepath. -func (c CaddyfileInput) Path() string { return c.Filepath } diff --git a/caddy/restart_windows.go b/caddy/restart_windows.go new file mode 100644 index 000000000..00ec94a71 --- /dev/null +++ b/caddy/restart_windows.go @@ -0,0 +1,25 @@ +package caddy + +func Restart(newCaddyfile Input) error { + if newCaddyfile == nil { + caddyfileMu.Lock() + newCaddyfile = caddyfile + caddyfileMu.Unlock() + } + + wg.Add(1) // barrier so Wait() doesn't unblock + + err := Stop() + if err != nil { + return err + } + + err = Start(newCaddyfile) + if err != nil { + return err + } + + wg.Done() // take down our barrier + + return nil +} diff --git a/caddy/sigtrap.go b/caddy/sigtrap.go new file mode 100644 index 000000000..b9cbec6a6 --- /dev/null +++ b/caddy/sigtrap.go @@ -0,0 +1,33 @@ +package caddy + +import ( + "log" + "os" + "os/signal" + + "github.com/mholt/caddy/server" +) + +func init() { + // Trap quit signals (cross-platform) + go func() { + shutdown := make(chan os.Signal, 1) + signal.Notify(shutdown, os.Interrupt, os.Kill) + <-shutdown + + var exitCode int + + serversMu.Lock() + errs := server.ShutdownCallbacks(servers) + serversMu.Unlock() + + if len(errs) > 0 { + for _, err := range errs { + log.Println(err) + } + exitCode = 1 + } + + os.Exit(exitCode) + }() +} diff --git a/caddy/sigtrap_posix.go b/caddy/sigtrap_posix.go new file mode 100644 index 000000000..789985efb --- /dev/null +++ b/caddy/sigtrap_posix.go @@ -0,0 +1,26 @@ +// +build !windows + +package caddy + +import ( + "log" + "os" + "os/signal" + "syscall" +) + +func init() { + // Trap POSIX-only signals + go func() { + reload := make(chan os.Signal, 1) + signal.Notify(reload, syscall.SIGUSR1) // reload configuration + + for { + <-reload + err := Restart(nil) + if err != nil { + log.Println(err) + } + } + }() +}