diff options
Diffstat (limited to 'src/vendor/github.com/stretchr/graceful')
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/.gitignore | 23 | ||||
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/LICENSE | 21 | ||||
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/README.md | 137 | ||||
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/graceful.go | 359 | ||||
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/graceful_test.go | 439 | ||||
| -rw-r--r-- | src/vendor/github.com/stretchr/graceful/tests/main.go | 40 |
6 files changed, 0 insertions, 1019 deletions
diff --git a/src/vendor/github.com/stretchr/graceful/.gitignore b/src/vendor/github.com/stretchr/graceful/.gitignore deleted file mode 100644 index 8365624..0000000 --- a/src/vendor/github.com/stretchr/graceful/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test diff --git a/src/vendor/github.com/stretchr/graceful/LICENSE b/src/vendor/github.com/stretchr/graceful/LICENSE deleted file mode 100644 index a4f2f28..0000000 --- a/src/vendor/github.com/stretchr/graceful/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Tyler Bunnell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/vendor/github.com/stretchr/graceful/README.md b/src/vendor/github.com/stretchr/graceful/README.md deleted file mode 100644 index 531249a..0000000 --- a/src/vendor/github.com/stretchr/graceful/README.md +++ /dev/null @@ -1,137 +0,0 @@ -graceful [](http://godoc.org/github.com/tylerb/graceful) [](https://drone.io/github.com/tylerb/graceful/latest) [](https://coveralls.io/r/tylerb/graceful?branch=dronedebug) [](https://gitter.im/tylerb/graceful?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -======== - -Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers. - -## Installation - -To install, simply execute: - -``` -go get gopkg.in/tylerb/graceful.v1 -``` - -I am using [gopkg.in](http://labix.org/gopkg.in) to control releases. - -## Usage - -Using Graceful is easy. Simply create your http.Handler and pass it to the `Run` function: - -```go -package main - -import ( - "gopkg.in/tylerb/graceful.v1" - "net/http" - "fmt" - "time" -) - -func main() { - mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - fmt.Fprintf(w, "Welcome to the home page!") - }) - - graceful.Run(":3001",10*time.Second,mux) -} -``` - -Another example, using [Negroni](https://github.com/codegangsta/negroni), functions in much the same manner: - -```go -package main - -import ( - "github.com/codegangsta/negroni" - "gopkg.in/tylerb/graceful.v1" - "net/http" - "fmt" - "time" -) - -func main() { - mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - fmt.Fprintf(w, "Welcome to the home page!") - }) - - n := negroni.Classic() - n.UseHandler(mux) - //n.Run(":3000") - graceful.Run(":3001",10*time.Second,n) -} -``` - -In addition to Run there are the http.Server counterparts ListenAndServe, ListenAndServeTLS and Serve, which allow you to configure HTTPS, custom timeouts and error handling. -Graceful may also be used by instantiating its Server type directly, which embeds an http.Server: - -```go -mux := // ... - -srv := &graceful.Server{ - Timeout: 10 * time.Second, - - Server: &http.Server{ - Addr: ":1234", - Handler: mux, - }, -} - -srv.ListenAndServe() -``` - -This form allows you to set the ConnState callback, which works in the same way as in http.Server: - -```go -mux := // ... - -srv := &graceful.Server{ - Timeout: 10 * time.Second, - - ConnState: func(conn net.Conn, state http.ConnState) { - // conn has a new state - }, - - Server: &http.Server{ - Addr: ":1234", - Handler: mux, - }, -} - -srv.ListenAndServe() -``` - -## Behaviour - -When Graceful is sent a SIGINT or SIGTERM (possibly from ^C or a kill command), it: - -1. Disables keepalive connections. -2. Closes the listening socket, allowing another process to listen on that port immediately. -3. Starts a timer of `timeout` duration to give active requests a chance to finish. -4. When timeout expires, closes all active connections. -5. Closes the `stopChan`, waking up any blocking goroutines. -6. Returns from the function, allowing the server to terminate. - -## Notes - -If the `timeout` argument to `Run` is 0, the server never times out, allowing all active requests to complete. - -If you wish to stop the server in some way other than an OS signal, you may call the `Stop()` function. -This function stops the server, gracefully, using the new timeout value you provide. The `StopChan()` function -returns a channel on which you can block while waiting for the server to stop. This channel will be closed when -the server is stopped, allowing your execution to proceed. Multiple goroutines can block on this channel at the -same time and all will be signalled when stopping is complete. - -## Contributing - -If you would like to contribute, please: - -1. Create a GitHub issue regarding the contribution. Features and bugs should be discussed beforehand. -2. Fork the repository. -3. Create a pull request with your solution. This pull request should reference and close the issues (Fix #2). - -All pull requests should: - -1. Pass [gometalinter -t .](https://github.com/alecthomas/gometalinter) with no warnings. -2. Be `go fmt` formatted. diff --git a/src/vendor/github.com/stretchr/graceful/graceful.go b/src/vendor/github.com/stretchr/graceful/graceful.go deleted file mode 100644 index d3a7175..0000000 --- a/src/vendor/github.com/stretchr/graceful/graceful.go +++ /dev/null @@ -1,359 +0,0 @@ -package graceful - -import ( - "crypto/tls" - "log" - "net" - "net/http" - "os" - "os/signal" - "sync" - "syscall" - "time" - - "golang.org/x/net/netutil" -) - -// Server wraps an http.Server with graceful connection handling. -// It may be used directly in the same way as http.Server, or may -// be constructed with the global functions in this package. -// -// Example: -// srv := &graceful.Server{ -// Timeout: 5 * time.Second, -// Server: &http.Server{Addr: ":1234", Handler: handler}, -// } -// srv.ListenAndServe() -type Server struct { - *http.Server - - // Timeout is the duration to allow outstanding requests to survive - // before forcefully terminating them. - Timeout time.Duration - - // Limit the number of outstanding requests - ListenLimit int - - // ConnState specifies an optional callback function that is - // called when a client connection changes state. This is a proxy - // to the underlying http.Server's ConnState, and the original - // must not be set directly. - ConnState func(net.Conn, http.ConnState) - - // BeforeShutdown is an optional callback function that is called - // before the listener is closed. - BeforeShutdown func() - - // ShutdownInitiated is an optional callback function that is called - // when shutdown is initiated. It can be used to notify the client - // side of long lived connections (e.g. websockets) to reconnect. - ShutdownInitiated func() - - // NoSignalHandling prevents graceful from automatically shutting down - // on SIGINT and SIGTERM. If set to true, you must shut down the server - // manually with Stop(). - NoSignalHandling bool - - // interrupt signals the listener to stop serving connections, - // and the server to shut down. - interrupt chan os.Signal - - // stopLock is used to protect against concurrent calls to Stop - stopLock sync.Mutex - - // stopChan is the channel on which callers may block while waiting for - // the server to stop. - stopChan chan struct{} - - // chanLock is used to protect access to the various channel constructors. - chanLock sync.RWMutex - - // connections holds all connections managed by graceful - connections map[net.Conn]struct{} -} - -// Run serves the http.Handler with graceful shutdown enabled. -// -// timeout is the duration to wait until killing active requests and stopping the server. -// If timeout is 0, the server never times out. It waits for all active requests to finish. -func Run(addr string, timeout time.Duration, n http.Handler) { - srv := &Server{ - Timeout: timeout, - Server: &http.Server{Addr: addr, Handler: n}, - } - - if err := srv.ListenAndServe(); err != nil { - if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") { - logger := log.New(os.Stdout, "[graceful] ", 0) - logger.Fatal(err) - } - } - -} - -// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled. -// -// timeout is the duration to wait until killing active requests and stopping the server. -// If timeout is 0, the server never times out. It waits for all active requests to finish. -func ListenAndServe(server *http.Server, timeout time.Duration) error { - srv := &Server{Timeout: timeout, Server: server} - return srv.ListenAndServe() -} - -// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled. -func (srv *Server) ListenAndServe() error { - // Create the listener so we can control their lifetime - addr := srv.Addr - if addr == "" { - addr = ":http" - } - l, err := net.Listen("tcp", addr) - if err != nil { - return err - } - - return srv.Serve(l) -} - -// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled. -// -// timeout is the duration to wait until killing active requests and stopping the server. -// If timeout is 0, the server never times out. It waits for all active requests to finish. -func ListenAndServeTLS(server *http.Server, certFile, keyFile string, timeout time.Duration) error { - srv := &Server{Timeout: timeout, Server: server} - return srv.ListenAndServeTLS(certFile, keyFile) -} - -// ListenTLS is a convenience method that creates an https listener using the -// provided cert and key files. Use this method if you need access to the -// listener object directly. When ready, pass it to the Serve method. -func (srv *Server) ListenTLS(certFile, keyFile string) (net.Listener, error) { - // Create the listener ourselves so we can control its lifetime - addr := srv.Addr - if addr == "" { - addr = ":https" - } - - config := &tls.Config{} - if srv.TLSConfig != nil { - *config = *srv.TLSConfig - } - if config.NextProtos == nil { - config.NextProtos = []string{"http/1.1"} - } - - var err error - config.Certificates = make([]tls.Certificate, 1) - config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return nil, err - } - - conn, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - - tlsListener := tls.NewListener(conn, config) - return tlsListener, nil -} - -// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled. -func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { - l, err := srv.ListenTLS(certFile, keyFile) - if err != nil { - return err - } - - return srv.Serve(l) -} - -// ListenAndServeTLSConfig can be used with an existing TLS config and is equivalent to -// http.Server.ListenAndServeTLS with graceful shutdown enabled, -func (srv *Server) ListenAndServeTLSConfig(config *tls.Config) error { - addr := srv.Addr - if addr == "" { - addr = ":https" - } - - conn, err := net.Listen("tcp", addr) - if err != nil { - return err - } - - tlsListener := tls.NewListener(conn, config) - return srv.Serve(tlsListener) -} - -// Serve is equivalent to http.Server.Serve with graceful shutdown enabled. -// -// timeout is the duration to wait until killing active requests and stopping the server. -// If timeout is 0, the server never times out. It waits for all active requests to finish. -func Serve(server *http.Server, l net.Listener, timeout time.Duration) error { - srv := &Server{Timeout: timeout, Server: server} - return srv.Serve(l) -} - -// Serve is equivalent to http.Server.Serve with graceful shutdown enabled. -func (srv *Server) Serve(listener net.Listener) error { - - if srv.ListenLimit != 0 { - listener = netutil.LimitListener(listener, srv.ListenLimit) - } - - // Track connection state - add := make(chan net.Conn) - remove := make(chan net.Conn) - - srv.Server.ConnState = func(conn net.Conn, state http.ConnState) { - switch state { - case http.StateNew: - add <- conn - case http.StateClosed, http.StateHijacked: - remove <- conn - } - if srv.ConnState != nil { - srv.ConnState(conn, state) - } - } - - // Manage open connections - shutdown := make(chan chan struct{}) - kill := make(chan struct{}) - go srv.manageConnections(add, remove, shutdown, kill) - - interrupt := srv.interruptChan() - // Set up the interrupt handler - if !srv.NoSignalHandling { - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) - } - quitting := make(chan struct{}) - go srv.handleInterrupt(interrupt, quitting, listener) - - // Serve with graceful listener. - // Execution blocks here until listener.Close() is called, above. - err := srv.Server.Serve(listener) - if err != nil { - // If the underlying listening is closed, Serve returns an error - // complaining about listening on a closed socket. This is expected, so - // let's ignore the error if we are the ones who explicitly closed the - // socket. - select { - case <-quitting: - err = nil - default: - } - } - - srv.shutdown(shutdown, kill) - - return err -} - -// Stop instructs the type to halt operations and close -// the stop channel when it is finished. -// -// timeout is grace period for which to wait before shutting -// down the server. The timeout value passed here will override the -// timeout given when constructing the server, as this is an explicit -// command to stop the server. -func (srv *Server) Stop(timeout time.Duration) { - srv.stopLock.Lock() - srv.Timeout = timeout - interrupt := srv.interruptChan() - interrupt <- syscall.SIGINT - srv.stopLock.Unlock() -} - -// StopChan gets the stop channel which will block until -// stopping has completed, at which point it is closed. -// Callers should never close the stop channel. -func (srv *Server) StopChan() <-chan struct{} { - srv.chanLock.Lock() - if srv.stopChan == nil { - srv.stopChan = make(chan struct{}) - } - srv.chanLock.Unlock() - return srv.stopChan -} - -func (srv *Server) manageConnections(add, remove chan net.Conn, shutdown chan chan struct{}, kill chan struct{}) { - var done chan struct{} - srv.connections = map[net.Conn]struct{}{} - for { - select { - case conn := <-add: - srv.connections[conn] = struct{}{} - case conn := <-remove: - delete(srv.connections, conn) - if done != nil && len(srv.connections) == 0 { - done <- struct{}{} - return - } - case done = <-shutdown: - if len(srv.connections) == 0 { - done <- struct{}{} - return - } - case <-kill: - for k := range srv.connections { - _ = k.Close() // nothing to do here if it errors - } - return - } - } -} - -func (srv *Server) interruptChan() chan os.Signal { - srv.chanLock.Lock() - if srv.interrupt == nil { - srv.interrupt = make(chan os.Signal, 1) - } - srv.chanLock.Unlock() - - return srv.interrupt -} - -func (srv *Server) handleInterrupt(interrupt chan os.Signal, quitting chan struct{}, listener net.Listener) { - <-interrupt - - if srv.BeforeShutdown != nil { - srv.BeforeShutdown() - } - - close(quitting) - srv.SetKeepAlivesEnabled(false) - _ = listener.Close() // we are shutting down anyway. ignore error. - - if srv.ShutdownInitiated != nil { - srv.ShutdownInitiated() - } - - srv.stopLock.Lock() - signal.Stop(interrupt) - close(interrupt) - srv.interrupt = nil - srv.stopLock.Unlock() -} - -func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) { - // Request done notification - done := make(chan struct{}) - shutdown <- done - - if srv.Timeout > 0 { - select { - case <-done: - case <-time.After(srv.Timeout): - close(kill) - } - } else { - <-done - } - // Close the stopChan to wake up any blocked goroutines. - srv.chanLock.Lock() - if srv.stopChan != nil { - close(srv.stopChan) - } - srv.chanLock.Unlock() -} diff --git a/src/vendor/github.com/stretchr/graceful/graceful_test.go b/src/vendor/github.com/stretchr/graceful/graceful_test.go deleted file mode 100644 index 83acac3..0000000 --- a/src/vendor/github.com/stretchr/graceful/graceful_test.go +++ /dev/null @@ -1,439 +0,0 @@ -package graceful - -import ( - "fmt" - "io" - "net" - "net/http" - "net/url" - "os" - "reflect" - "strings" - "sync" - "syscall" - "testing" - "time" -) - -var ( - killTime = 500 * time.Millisecond - timeoutTime = 1000 * time.Millisecond - waitTime = 100 * time.Millisecond -) - -func runQuery(t *testing.T, expected int, shouldErr bool, wg *sync.WaitGroup, once *sync.Once) { - wg.Add(1) - defer wg.Done() - client := http.Client{} - r, err := client.Get("http://localhost:9654") - if shouldErr && err == nil { - once.Do(func() { - t.Fatal("Expected an error but none was encountered.") - }) - } else if shouldErr && err != nil { - if checkErr(t, err, once) { - return - } - } - if r != nil && r.StatusCode != expected { - once.Do(func() { - t.Fatalf("Incorrect status code on response. Expected %d. Got %d", expected, r.StatusCode) - }) - } else if r == nil { - once.Do(func() { - t.Fatal("No response when a response was expected.") - }) - } -} - -func checkErr(t *testing.T, err error, once *sync.Once) bool { - if err.(*url.Error).Err == io.EOF { - return true - } - var errno syscall.Errno - switch oe := err.(*url.Error).Err.(type) { - case *net.OpError: - switch e := oe.Err.(type) { - case syscall.Errno: - errno = e - case *os.SyscallError: - errno = e.Err.(syscall.Errno) - } - if errno == syscall.ECONNREFUSED { - return true - } else if err != nil { - once.Do(func() { - t.Fatal("Error on Get:", err) - }) - } - default: - if strings.Contains(err.Error(), "transport closed before response was received") { - return true - } - fmt.Printf("unknown err: %s, %#v\n", err, err) - } - return false -} - -func createListener(sleep time.Duration) (*http.Server, net.Listener, error) { - mux := http.NewServeMux() - mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - time.Sleep(sleep) - rw.WriteHeader(http.StatusOK) - }) - - time.Sleep(1 * time.Second) - server := &http.Server{Addr: ":9654", Handler: mux} - l, err := net.Listen("tcp", ":9654") - if err != nil { - } - return server, l, err -} - -func runServer(timeout, sleep time.Duration, c chan os.Signal) error { - server, l, err := createListener(sleep) - if err != nil { - return err - } - - srv := &Server{Timeout: timeout, Server: server, interrupt: c} - return srv.Serve(l) -} - -func launchTestQueries(t *testing.T, wg *sync.WaitGroup, c chan os.Signal) { - var once sync.Once - for i := 0; i < 8; i++ { - go runQuery(t, http.StatusOK, false, wg, &once) - } - - time.Sleep(waitTime) - c <- os.Interrupt - time.Sleep(waitTime) - - for i := 0; i < 8; i++ { - go runQuery(t, 0, true, wg, &once) - } - - wg.Done() -} - -func TestGracefulRun(t *testing.T) { - c := make(chan os.Signal, 1) - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - runServer(killTime, killTime/2, c) - wg.Done() - }() - time.Sleep(1 * time.Second) - - wg.Add(1) - go launchTestQueries(t, &wg, c) - wg.Wait() -} - -func TestGracefulRunTimesOut(t *testing.T) { - c := make(chan os.Signal, 1) - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - runServer(killTime, killTime*10, c) - wg.Done() - }() - time.Sleep(2 * time.Second) - - var once sync.Once - wg.Add(1) - go func() { - for i := 0; i < 8; i++ { - go runQuery(t, 0, true, &wg, &once) - } - time.Sleep(waitTime) - c <- os.Interrupt - time.Sleep(waitTime) - for i := 0; i < 8; i++ { - go runQuery(t, 0, true, &wg, &once) - } - wg.Done() - }() - - wg.Wait() - -} - -func TestGracefulRunDoesntTimeOut(t *testing.T) { - c := make(chan os.Signal, 1) - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - runServer(0, killTime*2, c) - wg.Done() - }() - time.Sleep(1 * time.Second) - - wg.Add(1) - go launchTestQueries(t, &wg, c) - wg.Wait() -} - -func TestGracefulRunNoRequests(t *testing.T) { - c := make(chan os.Signal, 1) - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - runServer(0, killTime*2, c) - wg.Done() - }() - time.Sleep(1 * time.Second) - - c <- os.Interrupt - - wg.Wait() - -} - -func TestGracefulForwardsConnState(t *testing.T) { - c := make(chan os.Signal, 1) - states := make(map[http.ConnState]int) - var stateLock sync.Mutex - - connState := func(conn net.Conn, state http.ConnState) { - stateLock.Lock() - states[state]++ - stateLock.Unlock() - } - - var wg sync.WaitGroup - wg.Add(1) - - expected := map[http.ConnState]int{ - http.StateNew: 8, - http.StateActive: 8, - http.StateClosed: 8, - } - - go func() { - server, l, _ := createListener(killTime / 2) - srv := &Server{ - ConnState: connState, - Timeout: killTime, - Server: server, - interrupt: c, - } - srv.Serve(l) - - wg.Done() - }() - time.Sleep(2 * time.Second) - - wg.Add(1) - go launchTestQueries(t, &wg, c) - wg.Wait() - - stateLock.Lock() - if !reflect.DeepEqual(states, expected) { - t.Errorf("Incorrect connection state tracking.\n actual: %v\nexpected: %v\n", states, expected) - } - stateLock.Unlock() -} - -func TestGracefulExplicitStop(t *testing.T) { - server, l, err := createListener(1 * time.Millisecond) - if err != nil { - t.Fatal(err) - } - - srv := &Server{Timeout: killTime, Server: server} - - go func() { - go srv.Serve(l) - time.Sleep(waitTime) - srv.Stop(killTime) - }() - - // block on the stopChan until the server has shut down - select { - case <-srv.StopChan(): - case <-time.After(timeoutTime): - t.Fatal("Timed out while waiting for explicit stop to complete") - } -} - -func TestGracefulExplicitStopOverride(t *testing.T) { - server, l, err := createListener(1 * time.Millisecond) - if err != nil { - t.Fatal(err) - } - - srv := &Server{Timeout: killTime, Server: server} - - go func() { - go srv.Serve(l) - time.Sleep(waitTime) - srv.Stop(killTime / 2) - }() - - // block on the stopChan until the server has shut down - select { - case <-srv.StopChan(): - case <-time.After(killTime): - t.Fatal("Timed out while waiting for explicit stop to complete") - } -} - -func TestBeforeShutdownAndShutdownInitiatedCallbacks(t *testing.T) { - server, l, err := createListener(1 * time.Millisecond) - if err != nil { - t.Fatal(err) - } - - beforeShutdownCalled := make(chan struct{}) - cb1 := func() { close(beforeShutdownCalled) } - shutdownInitiatedCalled := make(chan struct{}) - cb2 := func() { close(shutdownInitiatedCalled) } - - srv := &Server{Server: server, BeforeShutdown: cb1, ShutdownInitiated: cb2} - - go func() { - go srv.Serve(l) - time.Sleep(waitTime) - srv.Stop(killTime) - }() - - beforeShutdown := false - shutdownInitiated := false - for i := 0; i < 2; i++ { - select { - case <-beforeShutdownCalled: - beforeShutdownCalled = nil - beforeShutdown = true - case <-shutdownInitiatedCalled: - shutdownInitiatedCalled = nil - shutdownInitiated = true - case <-time.After(killTime): - t.Fatal("Timed out while waiting for ShutdownInitiated callback to be called") - } - } - - if !beforeShutdown { - t.Fatal("beforeShutdown should be true") - } - if !shutdownInitiated { - t.Fatal("shutdownInitiated should be true") - } -} -func hijackingListener(srv *Server) (*http.Server, net.Listener, error) { - mux := http.NewServeMux() - mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - conn, bufrw, err := rw.(http.Hijacker).Hijack() - if err != nil { - http.Error(rw, "webserver doesn't support hijacking", http.StatusInternalServerError) - return - } - - defer conn.Close() - - bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n") - bufrw.Flush() - }) - - server := &http.Server{Addr: ":9654", Handler: mux} - l, err := net.Listen("tcp", ":9654") - return server, l, err -} - -func TestNotifyClosed(t *testing.T) { - c := make(chan os.Signal, 1) - - var wg sync.WaitGroup - wg.Add(1) - - srv := &Server{Timeout: killTime, interrupt: c} - server, l, err := hijackingListener(srv) - if err != nil { - t.Fatal(err) - } - - srv.Server = server - - go func() { - srv.Serve(l) - wg.Done() - }() - - var once sync.Once - for i := 0; i < 8; i++ { - runQuery(t, http.StatusOK, false, &wg, &once) - } - - srv.Stop(0) - - // block on the stopChan until the server has shut down - select { - case <-srv.StopChan(): - case <-time.After(timeoutTime): - t.Fatal("Timed out while waiting for explicit stop to complete") - } - - if len(srv.connections) > 0 { - t.Fatal("hijacked connections should not be managed") - } - -} - -func TestStopDeadlock(t *testing.T) { - c := make(chan struct{}) - - server, l, err := createListener(1 * time.Millisecond) - if err != nil { - t.Fatal(err) - } - - srv := &Server{Server: server, NoSignalHandling: true} - - go func() { - time.Sleep(waitTime) - srv.Serve(l) - }() - - go func() { - srv.Stop(0) - close(c) - }() - - select { - case <-c: - l.Close() - case <-time.After(timeoutTime): - t.Fatal("Timed out while waiting for explicit stop to complete") - } -} - -// Run with --race -func TestStopRace(t *testing.T) { - server, l, err := createListener(1 * time.Millisecond) - if err != nil { - t.Fatal(err) - } - - srv := &Server{Timeout: killTime, Server: server} - - go func() { - go srv.Serve(l) - srv.Stop(killTime) - }() - srv.Stop(0) - select { - case <-srv.StopChan(): - case <-time.After(timeoutTime): - t.Fatal("Timed out while waiting for explicit stop to complete") - } -} diff --git a/src/vendor/github.com/stretchr/graceful/tests/main.go b/src/vendor/github.com/stretchr/graceful/tests/main.go deleted file mode 100644 index 8c8fa20..0000000 --- a/src/vendor/github.com/stretchr/graceful/tests/main.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "fmt" - "sync" - - "github.com/codegangsta/negroni" - "github.com/tylerb/graceful" -) - -func main() { - - var wg sync.WaitGroup - - wg.Add(3) - go func() { - n := negroni.New() - fmt.Println("Launching server on :3000") - graceful.Run(":3000", 0, n) - fmt.Println("Terminated server on :3000") - wg.Done() - }() - go func() { - n := negroni.New() - fmt.Println("Launching server on :3001") - graceful.Run(":3001", 0, n) - fmt.Println("Terminated server on :3001") - wg.Done() - }() - go func() { - n := negroni.New() - fmt.Println("Launching server on :3002") - graceful.Run(":3002", 0, n) - fmt.Println("Terminated server on :3002") - wg.Done() - }() - fmt.Println("Press ctrl+c. All servers should terminate.") - wg.Wait() - -} |
