Commit a5b3f2b8 by Carl Bergquist Committed by GitHub

Merge pull request #10132 from bergquist/go_routine_management

Wait for all sub routines to finish before closing Grafana
parents 8e7166b5 f7ed2447
...@@ -95,7 +95,7 @@ func (hs *HttpServer) Start(ctx context.Context) error { ...@@ -95,7 +95,7 @@ func (hs *HttpServer) Start(ctx context.Context) error {
func (hs *HttpServer) Shutdown(ctx context.Context) error { func (hs *HttpServer) Shutdown(ctx context.Context) error {
err := hs.httpSrv.Shutdown(ctx) err := hs.httpSrv.Shutdown(ctx)
hs.log.Info("stopped http server") hs.log.Info("Stopped HTTP server")
return err return err
} }
......
...@@ -14,8 +14,8 @@ import ( ...@@ -14,8 +14,8 @@ import (
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
_ "github.com/grafana/grafana/pkg/services/alerting/conditions" _ "github.com/grafana/grafana/pkg/services/alerting/conditions"
...@@ -40,9 +40,6 @@ var homePath = flag.String("homepath", "", "path to grafana install/home path, d ...@@ -40,9 +40,6 @@ var homePath = flag.String("homepath", "", "path to grafana install/home path, d
var pidFile = flag.String("pidfile", "", "path to pid file") var pidFile = flag.String("pidfile", "", "path to pid file")
var exitChan = make(chan int) var exitChan = make(chan int)
func init() {
}
func main() { func main() {
v := flag.Bool("v", false, "prints current version and exits") v := flag.Bool("v", false, "prints current version and exits")
profile := flag.Bool("profile", false, "Turn on pprof profiling") profile := flag.Bool("profile", false, "Turn on pprof profiling")
...@@ -82,12 +79,28 @@ func main() { ...@@ -82,12 +79,28 @@ func main() {
setting.BuildStamp = buildstampInt64 setting.BuildStamp = buildstampInt64
metrics.M_Grafana_Version.WithLabelValues(version).Set(1) metrics.M_Grafana_Version.WithLabelValues(version).Set(1)
shutdownCompleted := make(chan int)
server := NewGrafanaServer() server := NewGrafanaServer()
server.Start()
go listenToSystemSignals(server, shutdownCompleted)
go func() {
code := 0
if err := server.Start(); err != nil {
log.Error2("Startup failed", "error", err)
code = 1
}
exitChan <- code
}()
code := <-shutdownCompleted
log.Info2("Grafana shutdown completed.", "code", code)
log.Close()
os.Exit(code)
} }
func listenToSystemSignals(server models.GrafanaServer) { func listenToSystemSignals(server *GrafanaServerImpl, shutdownCompleted chan int) {
signalChan := make(chan os.Signal, 1) signalChan := make(chan os.Signal, 1)
ignoreChan := make(chan os.Signal, 1) ignoreChan := make(chan os.Signal, 1)
code := 0 code := 0
...@@ -97,10 +110,12 @@ func listenToSystemSignals(server models.GrafanaServer) { ...@@ -97,10 +110,12 @@ func listenToSystemSignals(server models.GrafanaServer) {
select { select {
case sig := <-signalChan: case sig := <-signalChan:
// Stops trace if profiling has been enabled trace.Stop() // Stops trace if profiling has been enabled
trace.Stop()
server.Shutdown(0, fmt.Sprintf("system signal: %s", sig)) server.Shutdown(0, fmt.Sprintf("system signal: %s", sig))
shutdownCompleted <- 0
case code = <-exitChan: case code = <-exitChan:
trace.Stop() // Stops trace if profiling has been enabled
server.Shutdown(code, "startup error") server.Shutdown(code, "startup error")
shutdownCompleted <- code
} }
} }
...@@ -11,7 +11,6 @@ import ( ...@@ -11,7 +11,6 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
"github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/provisioning"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
...@@ -20,7 +19,6 @@ import ( ...@@ -20,7 +19,6 @@ import (
"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/cleanup" "github.com/grafana/grafana/pkg/services/cleanup"
...@@ -33,7 +31,7 @@ import ( ...@@ -33,7 +31,7 @@ import (
"github.com/grafana/grafana/pkg/tracing" "github.com/grafana/grafana/pkg/tracing"
) )
func NewGrafanaServer() models.GrafanaServer { func NewGrafanaServer() *GrafanaServerImpl {
rootCtx, shutdownFn := context.WithCancel(context.Background()) rootCtx, shutdownFn := context.WithCancel(context.Background())
childRoutines, childCtx := errgroup.WithContext(rootCtx) childRoutines, childCtx := errgroup.WithContext(rootCtx)
...@@ -54,9 +52,7 @@ type GrafanaServerImpl struct { ...@@ -54,9 +52,7 @@ type GrafanaServerImpl struct {
httpServer *api.HttpServer httpServer *api.HttpServer
} }
func (g *GrafanaServerImpl) Start() { func (g *GrafanaServerImpl) Start() error {
go listenToSystemSignals(g)
g.initLogging() g.initLogging()
g.writePIDFile() g.writePIDFile()
...@@ -69,16 +65,12 @@ func (g *GrafanaServerImpl) Start() { ...@@ -69,16 +65,12 @@ func (g *GrafanaServerImpl) Start() {
plugins.Init() plugins.Init()
if err := provisioning.Init(g.context, setting.HomePath, setting.Cfg); err != nil { if err := provisioning.Init(g.context, setting.HomePath, setting.Cfg); err != nil {
logger.Error("Failed to provision Grafana from config", "error", err) return fmt.Errorf("Failed to provision Grafana from config. error: %v", err)
g.Shutdown(1, "Startup failed")
return
} }
closer, err := tracing.Init(setting.Cfg) closer, err := tracing.Init(setting.Cfg)
if err != nil { if err != nil {
g.log.Error("Tracing settings is not valid", "error", err) return fmt.Errorf("Tracing settings is not valid. error: %v", err)
g.Shutdown(1, "Startup failed")
return
} }
defer closer.Close() defer closer.Close()
...@@ -93,13 +85,12 @@ func (g *GrafanaServerImpl) Start() { ...@@ -93,13 +85,12 @@ func (g *GrafanaServerImpl) Start() {
g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) }) g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) })
if err = notifications.Init(); err != nil { if err = notifications.Init(); err != nil {
g.log.Error("Notification service failed to initialize", "error", err) return fmt.Errorf("Notification service failed to initialize. error: %v", err)
g.Shutdown(1, "Startup failed")
return
} }
SendSystemdNotification("READY=1") sendSystemdNotification("READY=1")
g.startHttpServer()
return g.startHttpServer()
} }
func initSql() { func initSql() {
...@@ -123,16 +114,16 @@ func (g *GrafanaServerImpl) initLogging() { ...@@ -123,16 +114,16 @@ func (g *GrafanaServerImpl) initLogging() {
setting.LogConfigurationInfo() setting.LogConfigurationInfo()
} }
func (g *GrafanaServerImpl) startHttpServer() { func (g *GrafanaServerImpl) startHttpServer() error {
g.httpServer = api.NewHttpServer() g.httpServer = api.NewHttpServer()
err := g.httpServer.Start(g.context) err := g.httpServer.Start(g.context)
if err != nil { if err != nil {
g.log.Error("Fail to start server", "error", err) return fmt.Errorf("Fail to start server. error: %v", err)
g.Shutdown(1, "Startup failed")
return
} }
return nil
} }
func (g *GrafanaServerImpl) Shutdown(code int, reason string) { func (g *GrafanaServerImpl) Shutdown(code int, reason string) {
...@@ -145,10 +136,9 @@ func (g *GrafanaServerImpl) Shutdown(code int, reason string) { ...@@ -145,10 +136,9 @@ func (g *GrafanaServerImpl) Shutdown(code int, reason string) {
g.shutdownFn() g.shutdownFn()
err = g.childRoutines.Wait() err = g.childRoutines.Wait()
if err != nil && err != context.Canceled {
g.log.Info("Shutdown completed", "reason", err) g.log.Error("Server shutdown completed with an error", "error", err)
log.Close() }
os.Exit(code)
} }
func (g *GrafanaServerImpl) writePIDFile() { func (g *GrafanaServerImpl) writePIDFile() {
...@@ -173,7 +163,7 @@ func (g *GrafanaServerImpl) writePIDFile() { ...@@ -173,7 +163,7 @@ func (g *GrafanaServerImpl) writePIDFile() {
g.log.Info("Writing PID file", "path", *pidFile, "pid", pid) g.log.Info("Writing PID file", "path", *pidFile, "pid", pid)
} }
func SendSystemdNotification(state string) error { func sendSystemdNotification(state string) error {
notifySocket := os.Getenv("NOTIFY_SOCKET") notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket == "" { if notifySocket == "" {
......
package models
type GrafanaServer interface {
Start()
Shutdown(code int, reason string)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment