return errors instead of fataling
probably still need to cleanup coroutines
This commit is contained in:
parent
a98138a3e6
commit
13afde4bc1
@ -44,60 +44,68 @@ func (handlers Handlers) newListeners() ([]grace.Listener, error) {
|
||||
return listeners, nil
|
||||
}
|
||||
|
||||
// Serve on the given listeners.
|
||||
func (handlers Handlers) serve(listeners []grace.Listener) error {
|
||||
// Serve on the given listeners and wait for signals.
|
||||
func (handlers Handlers) serveWait(listeners []grace.Listener) error {
|
||||
if len(handlers) != len(listeners) {
|
||||
return ErrUnexpectedListenersCount
|
||||
}
|
||||
errch := make(chan error, len(listeners)+1) // listeners + grace.Wait
|
||||
for i, l := range listeners {
|
||||
go func(i int, l net.Listener) {
|
||||
err := http.Serve(l, handlers[i].Handler)
|
||||
// The underlying Accept() will return grace.ErrAlreadyClosed
|
||||
// when a signal to do the same is returned, which we are okay with.
|
||||
if err != nil && err != grace.ErrAlreadyClosed {
|
||||
log.Fatalf("Failed http.Serve: %s", err)
|
||||
errch <- fmt.Errorf("Failed http.Serve: %s", err)
|
||||
}
|
||||
}(i, l)
|
||||
}
|
||||
// TODO errors should be returned not fataled
|
||||
return nil
|
||||
go func() {
|
||||
err := grace.Wait(listeners)
|
||||
if err != nil {
|
||||
errch <- fmt.Errorf("Failed grace.Wait: %s", err)
|
||||
} else {
|
||||
errch <- nil
|
||||
}
|
||||
}()
|
||||
return <-errch
|
||||
}
|
||||
|
||||
// Serve will listen on the given address. It will also wait for a
|
||||
// SIGUSR2 signal and will restart the server passing the active listener
|
||||
// to the new process and avoid dropping active connections.
|
||||
func Serve(givenHandlers ...Handler) {
|
||||
func Serve(givenHandlers ...Handler) error {
|
||||
handlers := Handlers(givenHandlers)
|
||||
listeners, err := grace.Inherit()
|
||||
if err == nil {
|
||||
err = grace.CloseParent()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to close parent: %s", err)
|
||||
}
|
||||
if *verbose {
|
||||
log.Printf(
|
||||
"Graceful handoff of %s with new pid %d and old pid %d.",
|
||||
pprintAddr(listeners), os.Getpid(), os.Getppid())
|
||||
}
|
||||
err = grace.CloseParent()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to close parent: %s", err)
|
||||
}
|
||||
} else if err == grace.ErrNotInheriting {
|
||||
listeners, err = handlers.newListeners()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if *verbose {
|
||||
log.Printf("Serving %s with pid %d.", pprintAddr(listeners), os.Getpid())
|
||||
}
|
||||
} else {
|
||||
log.Fatalf("Failed graceful handoff: %s", err)
|
||||
return fmt.Errorf("Failed graceful handoff: %s", err)
|
||||
}
|
||||
go handlers.serve(listeners)
|
||||
err = grace.Wait(listeners)
|
||||
err = handlers.serveWait(listeners)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed grace.Wait: %s", err)
|
||||
return err
|
||||
}
|
||||
if *verbose {
|
||||
log.Printf("Exiting pid %d.", os.Getpid())
|
||||
return fmt.Errorf("Exiting pid %d.", os.Getpid())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Used for pretty printing addresses.
|
||||
|
Loading…
Reference in New Issue
Block a user