aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/zenazn/goji/graceful/graceful.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zenazn/goji/graceful/graceful.go')
-rw-r--r--vendor/github.com/zenazn/goji/graceful/graceful.go62
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
+}