diff --git a/cmd/main.go b/cmd/main.go index 4b90eb5..2f65baa 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,9 +1,12 @@ package main import ( + "context" "os" + "os/signal" "path/filepath" "runtime/debug" + "syscall" "github.com/urfave/cli" @@ -53,6 +56,15 @@ func action(cliCtx *cli.Context) error { logger.MainLog.Infoln("AMF version: ", version.GetVersion()) + ctx, cancel := context.WithCancel(context.Background()) + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) + + go func() { + <-sigCh // Wait for interrupt signal to gracefully shutdown + cancel() // Notify each goroutine and wait them stopped + }() + cfg, err := factory.ReadConfig(cliCtx.String("config")) if err != nil { return err @@ -60,7 +72,7 @@ func action(cliCtx *cli.Context) error { factory.AmfConfig = cfg appStart, appStop := utils.InitFunc(tlsKeyLogPath) - amf, err := service.NewApp(cfg, appStart, appStop, tlsKeyLogPath) + amf, err := service.NewApp(ctx, cfg, appStart, appStop, tlsKeyLogPath) if err != nil { return err } diff --git a/pkg/service/init.go b/pkg/service/init.go index 5c6ddec..5c53562 100644 --- a/pkg/service/init.go +++ b/pkg/service/init.go @@ -4,6 +4,8 @@ import ( "context" "io" "os" + "runtime/debug" + "sync" "github.com/sirupsen/logrus" @@ -31,6 +33,7 @@ type AmfApp struct { amfCtx *amf_context.AMFContext ctx context.Context cancel context.CancelFunc + wg sync.WaitGroup consumer *consumer.Consumer @@ -42,7 +45,7 @@ func GetApp() AmfAppInterface { return AMF } -func NewApp(cfg *factory.Config, startFunc, terminateFunc func(*AmfApp), tlsKeyLogPath string) (*AmfApp, error) { +func NewApp(ctx context.Context, cfg *factory.Config, startFunc, terminateFunc func(*AmfApp), tlsKeyLogPath string) (*AmfApp, error) { amf := &AmfApp{ cfg: cfg, start: startFunc, @@ -52,6 +55,7 @@ func NewApp(cfg *factory.Config, startFunc, terminateFunc func(*AmfApp), tlsKeyL amf.SetLogLevel(cfg.GetLogLevel()) amf.SetReportCaller(cfg.GetLogReportCaller()) + amf.ctx, amf.cancel = context.WithCancel(ctx) amf.amfCtx = amf_context.GetSelf() amf_context.InitAmfContext(amf.amfCtx) @@ -111,6 +115,8 @@ func (a *AmfApp) SetReportCaller(reportCaller bool) { func (a *AmfApp) Start(tlsKeyLogPath string) { logger.InitLog.Infoln("Server started") + a.wg.Add(1) + go a.listenShutdownEvent() a.start(a) } @@ -137,3 +143,16 @@ func (a *AmfApp) CancelContext() context.Context { func (a *AmfApp) Consumer() *consumer.Consumer { return a.consumer } + +func (a *AmfApp) listenShutdownEvent() { + defer func() { + if p := recover(); p != nil { + // Print stack for panic to log. Fatalf() will let program exit. + logger.MainLog.Fatalf("panic: %v\n%s", p, string(debug.Stack())) + } + a.wg.Done() + }() + + <-a.ctx.Done() + a.Terminate() +} diff --git a/pkg/utils/util.go b/pkg/utils/util.go index c7279c7..cbc9dc5 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -129,7 +129,9 @@ func InitFunc(tlsKeyLogPath string) (func(a *service.AmfApp), func(a *service.Am ngap_message.SendAMFStatusIndication(ran, unavailableGuamiList) return true }) + ngap_service.Stop() callback.SendAmfStatusChangeNotify((string)(models.StatusChange_UNAVAILABLE), amfSelf.ServedGuamiList) + } return appStart, appStop }