braintree / manners

A polite Go HTTP server that shuts down gracefully.
MIT License
997 stars 103 forks source link

doesn't shutdown when used with clients using persistent connections #19

Closed kmanley closed 9 years ago

kmanley commented 10 years ago

Try the program below. If you run it and press Ctrl-C it exits. If you run it, then hit localhost:8080/foo with firefox or chrome, then Ctrl-C the program, it will hang. This happens because the http.Server created inside func (s *GracefulServer) Serve(...) doesn't have a read timeout set.

There's an easy fix, I'll send a pull request.

package main

import (
    "fmt"
    "github.com/braintree/manners"
    "io"
    "net/http"
    "os"
    "os/signal"
    "syscall"
)

var quitChan = make(chan os.Signal, 1)
var server = manners.NewServer()

func Hello(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, "hello, world!\n")
}

/* it looks like manners only shuts down if the client doesn't use persistent connection;
   e.g. if you run this, then make a request with curl, then ctrl-c this process,
   it shuts down gracefully. But if you make the request with Chrome or Firefox,
   then ctrl-c this process, the http server doesn't quit until you close the
   browser tab (firefox) or entire browser (chrome) */
func waitForSignal() {
    fmt.Println("waiting for signal")
    <-quitChan
    fmt.Println("got signal")
    server.Shutdown <- true
}

func main() {

    signal.Notify(quitChan, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGTERM)
    http.HandleFunc("/foo", Hello)
    go waitForSignal()
    fmt.Println("listening...")
    server.ListenAndServe(":8080", nil)
    fmt.Println("exiting")
}
bryfry commented 10 years ago

Can confirm this behavior. Was trying to setup a reload after receiving a syscall.SIGINT. LisenAndServe stops serving new requests but hangs, preventing reload.

lionelbarrow commented 9 years ago

This is fixed with the merge of the non-backwards-compat branch.