fix bug introduced with systemd compatibility
This commit is contained in:
parent
faf45f4e9e
commit
991a4f1f05
41
grace.go
41
grace.go
@ -40,13 +40,23 @@ const (
|
||||
type Listener interface {
|
||||
net.Listener
|
||||
|
||||
// Will indicate that a Close is requested preventing further Accept. It will
|
||||
// also wait for the active connections to be terminated before returning.
|
||||
CloseRequest()
|
||||
|
||||
// Will return the underlying file representing this Listener.
|
||||
File() (f *os.File, err error)
|
||||
}
|
||||
|
||||
// A realListener is a real file backed net.Listener.
|
||||
type realListener interface {
|
||||
net.Listener
|
||||
File() (f *os.File, err error)
|
||||
}
|
||||
|
||||
// A goroutine based counter that provides graceful Close for listeners.
|
||||
type listener struct {
|
||||
Listener
|
||||
realListener
|
||||
closed bool // Indicates we're already closed.
|
||||
closeRequest chan bool // Send a bool here to indicate we want to Close.
|
||||
allClosed chan bool // Receive from here will indicate a clean Close.
|
||||
@ -65,9 +75,9 @@ func (c conn) Close() error {
|
||||
}
|
||||
|
||||
// Wraps an existing File listener to provide a graceful Close() process.
|
||||
func NewListener(l Listener) Listener {
|
||||
func NewListener(l realListener) Listener {
|
||||
i := &listener{
|
||||
Listener: l,
|
||||
realListener: l,
|
||||
closeRequest: make(chan bool),
|
||||
allClosed: make(chan bool),
|
||||
counter: make(chan bool),
|
||||
@ -97,20 +107,24 @@ func (l *listener) enabler() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *listener) Close() error {
|
||||
func (l *listener) CloseRequest() {
|
||||
if l.closed == true {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
l.closeRequest <- true
|
||||
<-l.allClosed
|
||||
return l.Listener.Close()
|
||||
}
|
||||
|
||||
func (l *listener) Close() error {
|
||||
l.CloseRequest()
|
||||
return l.realListener.Close()
|
||||
}
|
||||
|
||||
func (l *listener) Accept() (net.Conn, error) {
|
||||
if l.closed == true {
|
||||
return nil, ErrAlreadyClosed
|
||||
}
|
||||
c, err := l.Listener.Accept()
|
||||
c, err := l.realListener.Accept()
|
||||
if err != nil {
|
||||
if strings.HasSuffix(err.Error(), errClosed) {
|
||||
return nil, ErrAlreadyClosed
|
||||
@ -132,16 +146,17 @@ func Wait(listeners []Listener) (err error) {
|
||||
sig := <-ch
|
||||
switch sig {
|
||||
case syscall.SIGTERM:
|
||||
if os.Getppid() == 1 { // init provided sockets dont close
|
||||
return nil
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(listeners))
|
||||
for _, l := range listeners {
|
||||
go func(l Listener) {
|
||||
cErr := l.Close()
|
||||
if cErr != nil {
|
||||
err = cErr
|
||||
if os.Getppid() == 1 { // init provided sockets dont actually close
|
||||
l.CloseRequest()
|
||||
} else {
|
||||
cErr := l.Close()
|
||||
if cErr != nil {
|
||||
err = cErr
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}(l)
|
||||
|
@ -24,8 +24,17 @@ const (
|
||||
// The amount of time for the long HTTP request. This should be
|
||||
// bigger than the value above.
|
||||
slowHttpWait = time.Second * 4
|
||||
|
||||
// Debug logging.
|
||||
debugLog = false
|
||||
)
|
||||
|
||||
func debug(format string, a ...interface{}) {
|
||||
if debugLog {
|
||||
println(fmt.Sprintf(format, a...))
|
||||
}
|
||||
}
|
||||
|
||||
// The response from the test server.
|
||||
type response struct {
|
||||
Sleep time.Duration
|
||||
@ -162,6 +171,7 @@ func (h *harness) RemoveExe() {
|
||||
|
||||
// Helper for sending a single request.
|
||||
func (h *harness) SendOne(duration time.Duration, addr string, pid int) {
|
||||
debug("Send One pid=%d duration=%s", pid, duration)
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{DisableKeepAlives: true},
|
||||
}
|
||||
@ -179,6 +189,7 @@ func (h *harness) SendOne(duration time.Duration, addr string, pid int) {
|
||||
if pid != res.Pid {
|
||||
h.T.Fatalf("Didn't get expected pid %d instead got %d", pid, res.Pid)
|
||||
}
|
||||
debug("Request Done pid=%d duration=%s", pid, duration)
|
||||
h.RequestWaitGroup.Done()
|
||||
}
|
||||
|
||||
@ -186,6 +197,7 @@ func (h *harness) SendOne(duration time.Duration, addr string, pid int) {
|
||||
func (h *harness) SendRequest() {
|
||||
pid := h.MostRecentProcess().Pid
|
||||
for _, addr := range h.Addr {
|
||||
debug("Added 2 Requests")
|
||||
h.RequestWaitGroup.Add(2)
|
||||
go h.SendOne(time.Second*0, addr, pid)
|
||||
go h.SendOne(slowHttpWait, addr, pid)
|
||||
@ -199,21 +211,35 @@ func (h *harness) Wait() {
|
||||
|
||||
// The main test case.
|
||||
func TestComplex(t *testing.T) {
|
||||
debug("Started TestComplex")
|
||||
h := &harness{
|
||||
ImportPath: "github.com/daaku/go.grace/gracehttp/testserver",
|
||||
T: t,
|
||||
}
|
||||
debug("Building")
|
||||
h.Build()
|
||||
debug("Initial Start")
|
||||
h.Start()
|
||||
debug("Send Request 1")
|
||||
h.SendRequest()
|
||||
debug("Sleeping 1")
|
||||
time.Sleep(processWait)
|
||||
debug("Restart 1")
|
||||
h.Restart()
|
||||
debug("Send Request 2")
|
||||
h.SendRequest()
|
||||
debug("Sleeping 2")
|
||||
time.Sleep(processWait)
|
||||
debug("Restart 2")
|
||||
h.Restart()
|
||||
debug("Send Request 3")
|
||||
h.SendRequest()
|
||||
debug("Sleeping 3")
|
||||
time.Sleep(processWait)
|
||||
debug("Stopping")
|
||||
h.Stop()
|
||||
debug("Waiting")
|
||||
h.Wait()
|
||||
debug("Removing Executable")
|
||||
h.RemoveExe()
|
||||
}
|
||||
|
@ -24,15 +24,22 @@ var (
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
err := json.NewEncoder(os.Stderr).Encode(&response{Pid: os.Getpid()})
|
||||
err := flag.Set("gracehttp.log", "false")
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting gracehttp.log: %s", err)
|
||||
}
|
||||
err = json.NewEncoder(os.Stderr).Encode(&response{Pid: os.Getpid()})
|
||||
if err != nil {
|
||||
log.Fatalf("Error writing startup json: %s", err)
|
||||
}
|
||||
gracehttp.Serve(
|
||||
err = gracehttp.Serve(
|
||||
gracehttp.Handler{*address0, newHandler()},
|
||||
gracehttp.Handler{*address1, newHandler()},
|
||||
gracehttp.Handler{*address2, newHandler()},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in gracehttp.Serve: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newHandler() http.Handler {
|
||||
|
Loading…
Reference in New Issue
Block a user