Make Control safe to stop and wait on from any lifecycle state (#1794)

This commit is contained in:
Nate Brown
2026-07-10 10:35:17 -05:00
committed by GitHub
parent 5ecdd4eaa9
commit ab736e4c6b
10 changed files with 441 additions and 58 deletions
+8 -4
View File
@@ -53,7 +53,12 @@ func main() {
l := logging.NewLogger(os.Stdout)
if *serviceFlag != "" {
if err := doService(configPath, configTest, Build, serviceFlag); err != nil {
if *configTest {
fmt.Println("-test is not supported with -service, run the config test without -service")
os.Exit(1)
}
if err := doService(configPath, Build, serviceFlag); err != nil {
l.Error("Service command failed", "error", err)
os.Exit(1)
}
@@ -93,15 +98,14 @@ func main() {
}
if !*configTest {
wait, err := ctrl.Start()
if err != nil {
if err := ctrl.Start(); err != nil {
util.LogWithContextIfNeeded("Error while running", err, l)
os.Exit(1)
}
go ctrl.ShutdownBlock()
if err := wait(); err != nil {
if err := ctrl.Wait(); err != nil {
l.Error("Nebula stopped due to fatal error", "error", err)
os.Exit(2)
}
+25 -6
View File
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/kardianos/service"
"github.com/slackhq/nebula"
@@ -14,7 +15,6 @@ var logger service.Logger
type program struct {
configPath *string
configTest *bool
build string
control *nebula.Control
}
@@ -40,22 +40,41 @@ func (p *program) Start(s service.Service) error {
}
})
p.control, err = nebula.Main(c, *p.configTest, Build, l, nil)
p.control, err = nebula.Main(c, false, Build, l, nil)
if err != nil {
return err
}
p.control.Start()
if err := p.control.Start(); err != nil {
return err
}
// Nebula can stop itself on a fatal packet reader error, make sure to log it if it happens.
go func() {
if err := p.control.Wait(); err != nil {
logger.Error(fmt.Sprintf("Nebula stopped due to fatal error: %v", err))
os.Exit(2)
}
}()
return nil
}
func (p *program) Stop(s service.Service) error {
logger.Info("Nebula service stopping.")
if p.control == nil {
return nil
}
p.control.Stop()
// block until nebula has fully drained before reporting stopped.
// error logging is handled by Start.
_ = p.control.Wait()
return nil
}
func doService(configPath *string, configTest *bool, build string, serviceFlag *string) error {
func doService(configPath *string, build string, serviceFlag *string) error {
if *configPath == "" {
p, err := config.DefaultPath()
if err != nil {
@@ -73,7 +92,6 @@ func doService(configPath *string, configTest *bool, build string, serviceFlag *
prg := &program{
configPath: configPath,
configTest: configTest,
build: build,
}
@@ -105,8 +123,9 @@ func doService(configPath *string, configTest *bool, build string, serviceFlag *
switch *serviceFlag {
case "run":
if err := s.Run(); err != nil {
// Route any errors to the system logger
// Route any errors to the system logger and report the failure
logger.Error(err)
return err
}
default:
if err := service.Control(s, *serviceFlag); err != nil {
+2 -3
View File
@@ -84,8 +84,7 @@ func main() {
}
if !*configTest {
wait, err := ctrl.Start()
if err != nil {
if err := ctrl.Start(); err != nil {
util.LogWithContextIfNeeded("Error while running", err, l)
os.Exit(1)
}
@@ -93,7 +92,7 @@ func main() {
go ctrl.ShutdownBlock()
notifyReady(l)
if err := wait(); err != nil {
if err := ctrl.Wait(); err != nil {
l.Error("Nebula stopped due to fatal error", "error", err)
os.Exit(2)
}