aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatthew Holt <[email protected]>2016-06-23 18:02:12 -0600
committerMatthew Holt <[email protected]>2016-06-23 18:02:12 -0600
commit15fa5cf2da0b721066210afab45cd2599ee0dd68 (patch)
tree57d8fedb31060bf306d4a19ecc00cfaca2b5fc40
parentb49f65d5de76bbc3faaba93110cf0afd3f58bb31 (diff)
downloadcaddy-15fa5cf2da0b721066210afab45cd2599ee0dd68.tar.gz
caddy-15fa5cf2da0b721066210afab45cd2599ee0dd68.zip
OnFirstStartup and OnFinalShutdown callbacks added
OnStartup and OnShutdown callbacks now run as part of restarts, too. The startup and shutdown directives only run their commands NOT as part of restarts, as before. Some middleware that use OnStartup may need to switch to OnFirstStartup and implement OnFinalShutdown to do any cleanup as needed.
-rw-r--r--caddy.go40
-rw-r--r--caddyhttp/errors/errors.go3
-rw-r--r--caddyhttp/errors/setup.go11
-rw-r--r--caddyhttp/log/log.go2
-rw-r--r--caddyhttp/log/setup.go11
-rw-r--r--controller.go16
-rw-r--r--sigtrap.go2
-rw-r--r--startupshutdown/startupshutdown.go4
8 files changed, 73 insertions, 16 deletions
diff --git a/caddy.go b/caddy.go
index c52891af0..568d682f1 100644
--- a/caddy.go
+++ b/caddy.go
@@ -73,10 +73,12 @@ type Instance struct {
// servers is the list of servers with their listeners.
servers []serverListener
- // these are callbacks to execute when certain events happen
- onStartup []func() error
- onRestart []func() error
- onShutdown []func() error
+ // these callbacks execute when certain events occur
+ onFirstStartup []func() error // starting, not as part of a restart
+ onStartup []func() error // starting, even as part of a restart
+ onRestart []func() error // before restart commences
+ onShutdown []func() error // stopping, even as part of a restart
+ onFinalShutdown []func() error // stopping, not as part of a restart
}
// Stop stops all servers contained in i. It does NOT
@@ -104,10 +106,11 @@ func (i *Instance) Stop() error {
return nil
}
-// shutdownCallbacks executes all the shutdown callbacks of i.
-// An error returned from one does not stop execution of the rest.
-// All the errors will be returned.
-func (i *Instance) shutdownCallbacks() []error {
+// ShutdownCallbacks executes all the shutdown callbacks of i,
+// including ones that are scheduled only for the final shutdown
+// of i. An error returned from one does not stop execution of
+// the rest. All the non-nil errors will be returned.
+func (i *Instance) ShutdownCallbacks() []error {
var errs []error
for _, shutdownFunc := range i.onShutdown {
err := shutdownFunc()
@@ -115,6 +118,12 @@ func (i *Instance) shutdownCallbacks() []error {
errs = append(errs, err)
}
}
+ for _, finalShutdownFunc := range i.onFinalShutdown {
+ err := finalShutdownFunc()
+ if err != nil {
+ errs = append(errs, err)
+ }
+ }
return errs
}
@@ -159,6 +168,12 @@ func (i *Instance) Restart(newCaddyfile Input) (*Instance, error) {
}
// success! stop the old instance
+ for _, shutdownFunc := range i.onShutdown {
+ err := shutdownFunc()
+ if err != nil {
+ return i, err
+ }
+ }
i.Stop()
log.Println("[INFO] Reloading complete")
@@ -409,6 +424,15 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r
return err
}
+ // run startup callbacks
+ if restartFds == nil {
+ for _, firstStartupFunc := range inst.onFirstStartup {
+ err := firstStartupFunc()
+ if err != nil {
+ return err
+ }
+ }
+ }
for _, startupFunc := range inst.onStartup {
err := startupFunc()
if err != nil {
diff --git a/caddyhttp/errors/errors.go b/caddyhttp/errors/errors.go
index f933adcd1..8d4dd84a0 100644
--- a/caddyhttp/errors/errors.go
+++ b/caddyhttp/errors/errors.go
@@ -29,7 +29,8 @@ type ErrorHandler struct {
LogFile string
Log *log.Logger
LogRoller *httpserver.LogRoller
- Debug bool // if true, errors are written out to client rather than to a log
+ Debug bool // if true, errors are written out to client rather than to a log
+ file *os.File // a log file to close when done
}
func (h ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
diff --git a/caddyhttp/errors/setup.go b/caddyhttp/errors/setup.go
index 36ef74d55..2b3b6dafd 100644
--- a/caddyhttp/errors/setup.go
+++ b/caddyhttp/errors/setup.go
@@ -49,11 +49,10 @@ func setup(c *caddy.Controller) error {
}
if handler.LogRoller != nil {
file.Close()
-
handler.LogRoller.Filename = handler.LogFile
-
writer = handler.LogRoller.GetLogWriter()
} else {
+ handler.file = file
writer = file
}
}
@@ -62,6 +61,14 @@ func setup(c *caddy.Controller) error {
return nil
})
+ // When server stops, close any open log file
+ c.OnShutdown(func() error {
+ if handler.file != nil {
+ handler.file.Close()
+ }
+ return nil
+ })
+
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
handler.Next = next
return handler
diff --git a/caddyhttp/log/log.go b/caddyhttp/log/log.go
index e266f84f5..4d2f85037 100644
--- a/caddyhttp/log/log.go
+++ b/caddyhttp/log/log.go
@@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
+ "os"
"github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver"
@@ -67,6 +68,7 @@ type Rule struct {
Format string
Log *log.Logger
Roller *httpserver.LogRoller
+ file *os.File // if logging to a file that needs to be closed
}
const (
diff --git a/caddyhttp/log/setup.go b/caddyhttp/log/setup.go
index ddb39da6d..8cdad9f85 100644
--- a/caddyhttp/log/setup.go
+++ b/caddyhttp/log/setup.go
@@ -43,6 +43,7 @@ func setup(c *caddy.Controller) error {
rules[i].Roller.Filename = rules[i].OutputFile
writer = rules[i].Roller.GetLogWriter()
} else {
+ rules[i].file = file
writer = file
}
}
@@ -53,6 +54,16 @@ func setup(c *caddy.Controller) error {
return nil
})
+ // When server stops, close any open log files
+ c.OnShutdown(func() error {
+ for _, rule := range rules {
+ if rule.file != nil {
+ rule.file.Close()
+ }
+ }
+ return nil
+ })
+
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
return Logger{Next: next, Rules: rules, ErrorFunc: httpserver.DefaultErrorFunc}
})
diff --git a/controller.go b/controller.go
index 3c25e4879..890534f9b 100644
--- a/controller.go
+++ b/controller.go
@@ -54,8 +54,14 @@ func (c *Controller) ServerType() string {
return c.instance.serverType
}
+// OnFirstStartup adds fn to the list of callback functions to execute
+// when the server is about to be started NOT as part of a restart.
+func (c *Controller) OnFirstStartup(fn func() error) {
+ c.instance.onFirstStartup = append(c.instance.onFirstStartup, fn)
+}
+
// OnStartup adds fn to the list of callback functions to execute
-// when the server is about to be started.
+// when the server is about to be started (including restarts).
func (c *Controller) OnStartup(fn func() error) {
c.instance.onStartup = append(c.instance.onStartup, fn)
}
@@ -67,11 +73,17 @@ func (c *Controller) OnRestart(fn func() error) {
}
// OnShutdown adds fn to the list of callback functions to execute
-// when the server is about to be shut down..
+// when the server is about to be shut down (including restarts).
func (c *Controller) OnShutdown(fn func() error) {
c.instance.onShutdown = append(c.instance.onShutdown, fn)
}
+// OnFinalShutdown adds fn to the list of callback functions to execute
+// when the server is about to be shut down NOT as part of a restart.
+func (c *Controller) OnFinalShutdown(fn func() error) {
+ c.instance.onFinalShutdown = append(c.instance.onFinalShutdown, fn)
+}
+
// Context gets the context associated with the instance associated with c.
func (c *Controller) Context() Context {
return c.instance.context
diff --git a/sigtrap.go b/sigtrap.go
index 7acdbc491..ed7dc803a 100644
--- a/sigtrap.go
+++ b/sigtrap.go
@@ -72,7 +72,7 @@ func allShutdownCallbacks() []error {
var errs []error
instancesMu.Lock()
for _, inst := range instances {
- errs = append(errs, inst.shutdownCallbacks()...)
+ errs = append(errs, inst.ShutdownCallbacks()...)
}
instancesMu.Unlock()
return errs
diff --git a/startupshutdown/startupshutdown.go b/startupshutdown/startupshutdown.go
index 0a14e0c82..908a4f9cc 100644
--- a/startupshutdown/startupshutdown.go
+++ b/startupshutdown/startupshutdown.go
@@ -15,12 +15,12 @@ func init() {
// Startup registers a startup callback to execute during server start.
func Startup(c *caddy.Controller) error {
- return registerCallback(c, c.OnStartup)
+ return registerCallback(c, c.OnFirstStartup)
}
// Shutdown registers a shutdown callback to execute during server stop.
func Shutdown(c *caddy.Controller) error {
- return registerCallback(c, c.OnShutdown)
+ return registerCallback(c, c.OnFinalShutdown)
}
// registerCallback registers a callback function to execute by