diff options
Diffstat (limited to 'vendor/github.com/zenazn/goji/graceful/graceful.go')
| -rw-r--r-- | vendor/github.com/zenazn/goji/graceful/graceful.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/vendor/github.com/zenazn/goji/graceful/graceful.go b/vendor/github.com/zenazn/goji/graceful/graceful.go new file mode 100644 index 0000000..ff9b186 --- /dev/null +++ b/vendor/github.com/zenazn/goji/graceful/graceful.go @@ -0,0 +1,62 @@ +/* +Package graceful implements graceful shutdown for HTTP servers by closing idle +connections after receiving a signal. By default, this package listens for +interrupts (i.e., SIGINT), but when it detects that it is running under Einhorn +it will additionally listen for SIGUSR2 as well, giving your application +automatic support for graceful restarts/code upgrades. +*/ +package graceful + +import ( + "net" + "runtime" + "sync/atomic" + + "github.com/zenazn/goji/graceful/listener" +) + +// WrapListener wraps an arbitrary net.Listener for use with graceful shutdowns. +// In the background, it uses the listener sub-package to Wrap the listener in +// Deadline mode. If another mode of operation is desired, you should call +// listener.Wrap yourself: this function is smart enough to not double-wrap +// listeners. +func WrapListener(l net.Listener) net.Listener { + if lt, ok := l.(*listener.T); ok { + appendListener(lt) + return lt + } + + lt := listener.Wrap(l, listener.Deadline) + appendListener(lt) + return lt +} + +func appendListener(l *listener.T) { + mu.Lock() + defer mu.Unlock() + + listeners = append(listeners, l) +} + +const errClosing = "use of closed network connection" + +// During graceful shutdown, calls to Accept will start returning errors. This +// is inconvenient, since we know these sorts of errors are peaceful, so we +// silently swallow them. +func peacefulError(err error) error { + if atomic.LoadInt32(&closing) == 0 { + return err + } + // Unfortunately Go doesn't really give us a better way to select errors + // than this, so *shrug*. + if oe, ok := err.(*net.OpError); ok { + errOp := "accept" + if runtime.GOOS == "windows" { + errOp = "AcceptEx" + } + if oe.Op == errOp && oe.Err.Error() == errClosing { + return nil + } + } + return err +} |
