fix: fixed race condition between http.Server ListenAndServe & Shutdown, now service crash during startup correctly closes http server every time

This commit is contained in:
Torkel Ödegaard
2018-05-02 18:10:21 +02:00
parent d04ad835e2
commit 23655315b8
3 changed files with 29 additions and 9 deletions

View File

@@ -71,6 +71,8 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
// handle http shutdown on server context done
go func() {
<-ctx.Done()
// Hacky fix for race condition between ListenAndServe and Shutdown
time.Sleep(time.Millisecond * 100)
if err := hs.httpSrv.Shutdown(context.Background()); err != nil {
hs.log.Error("Failed to shutdown server", "error", err)
}

View File

@@ -86,7 +86,7 @@ func main() {
go listenToSystemSignals(server)
err := server.Start()
err := server.Run()
trace.Stop()
log.Close()

View File

@@ -60,12 +60,13 @@ type GrafanaServerImpl struct {
log log.Logger
cfg *setting.Cfg
shutdownReason string
shutdownInProgress bool
RouteRegister api.RouteRegister `inject:""`
HttpServer *api.HTTPServer `inject:""`
}
func (g *GrafanaServerImpl) Start() error {
func (g *GrafanaServerImpl) Run() error {
g.loadConfiguration()
g.writePIDFile()
@@ -129,8 +130,24 @@ func (g *GrafanaServerImpl) Start() error {
}
g.childRoutines.Go(func() error {
// Skip starting new service is we are shutting down
// Ccan happen when service crash during startup
if g.shutdownInProgress {
return nil
}
err := service.Run(g.context)
// If error is not canceled then the service crashed
if err != context.Canceled {
g.log.Error("Stopped "+reflect.TypeOf(service).Elem().Name(), "reason", err)
} else {
g.log.Info("Stopped "+reflect.TypeOf(service).Elem().Name(), "reason", err)
}
// Mark that we are in shutdown mode
// So more services are not started
g.shutdownInProgress = true
return err
})
}
@@ -159,6 +176,7 @@ func (g *GrafanaServerImpl) loadConfiguration() {
func (g *GrafanaServerImpl) Shutdown(reason string) {
g.log.Info("Shutdown started", "reason", reason)
g.shutdownReason = reason
g.shutdownInProgress = true
// call cancel func on root context
g.shutdownFn()