diff --git a/api.go b/api.go index 92579b6..7fc4740 100644 --- a/api.go +++ b/api.go @@ -359,6 +359,8 @@ func (app *appContext) ModifyConfig(gc *gin.Context) { } else { RESTART <- true } + // Safety Sleep (Ensure shutdown tasks get done) + time.Sleep(time.Second) } app.loadConfig() // Reinitialize password validator on config change, as opposed to every applicable request like in python. @@ -527,5 +529,7 @@ func (app *appContext) Restart() error { } else { RESTART <- true } + // Safety Sleep (Ensure shutdown tasks get done) + time.Sleep(time.Second) return nil } diff --git a/discord.go b/discord.go index 14fc59c..7362fa3 100644 --- a/discord.go +++ b/discord.go @@ -120,7 +120,7 @@ func (d *DiscordDaemon) run() { defer d.deregisterCommands() defer d.bot.Close() - d.registerCommands() + go d.registerCommands() <-d.ShutdownChannel d.ShutdownChannel <- "Down" diff --git a/main.go b/main.go index c07f6f8..fb6c725 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "path/filepath" "runtime" "strings" + "syscall" "time" "github.com/fatih/color" @@ -43,12 +44,14 @@ var ( SWAGGER *bool QUIT = false RUNNING = false - warning = color.New(color.FgYellow).SprintfFunc() - info = color.New(color.FgMagenta).SprintfFunc() - hiwhite = color.New(color.FgHiWhite).SprintfFunc() - white = color.New(color.FgWhite).SprintfFunc() - version string - commit string + // Used to know how many times to re-broadcast restart signal. + RESTARTLISTENERCOUNT = 0 + warning = color.New(color.FgYellow).SprintfFunc() + info = color.New(color.FgMagenta).SprintfFunc() + hiwhite = color.New(color.FgHiWhite).SprintfFunc() + white = color.New(color.FgWhite).SprintfFunc() + version string + commit string ) var temp = func() string { @@ -102,7 +105,6 @@ type appContext struct { host string port int version string - quit chan os.Signal URLBase string updater *Updater newUpdate bool // Whether whatever's in update is new. @@ -152,6 +154,7 @@ func test(app *appContext) { } func start(asDaemon, firstCall bool) { + RESTARTLISTENERCOUNT = 0 RUNNING = true defer func() { RUNNING = false }() @@ -250,7 +253,7 @@ func start(asDaemon, firstCall bool) { app.err.Fatalf("Couldn't establish socket connection at %s\n", SOCK) } c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c os.Remove(SOCK) @@ -578,40 +581,38 @@ func start(asDaemon, firstCall bool) { } else { app.info.Printf("Loaded @ %s", address) } - app.quit = make(chan os.Signal) - signal.Notify(app.quit, os.Interrupt) - go func() { - for range app.quit { - app.shutdown() - } - }() - for range RESTART { - println("got it too!") - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := SRV.Shutdown(ctx); err != nil { - app.err.Fatalf("Server shutdown error: %s", err) - } - app.info.Println("Server shut down.") - return + + waitForRestart() + + app.info.Printf("Restart/Quit signal received, give me a second!") + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if err := SRV.Shutdown(ctx); err != nil { + app.err.Fatalf("Server shutdown error: %s", err) } + app.info.Println("Server shut down.") + return } -func (app *appContext) shutdown() { - app.info.Println("Shutting down...") +func shutdown() { QUIT = true RESTART <- true - for { - if RUNNING { - continue - } - cntx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := SRV.Shutdown(cntx); err != nil { - app.err.Fatalf("Server shutdown error: %s", err) - } + // Safety Sleep (Ensure shutdown tasks get done) + time.Sleep(time.Second) +} - os.Exit(1) +func (app *appContext) shutdown() { + app.info.Println("Shutting down...") + shutdown() +} + +// Receives a restart signal and re-broadcasts it for other components. +func waitForRestart() { + RESTARTLISTENERCOUNT++ + <-RESTART + RESTARTLISTENERCOUNT-- + if RESTARTLISTENERCOUNT > 0 { + RESTART <- true } } @@ -686,6 +687,15 @@ func main() { TEST = true } loadFilesystems() + + quit := make(chan os.Signal, 0) + signal.Notify(quit, os.Interrupt, syscall.SIGTERM) + // defer close(quit) + go func() { + <-quit + shutdown() + }() + if flagPassed("start") { args := []string{} for i, f := range os.Args { @@ -760,7 +770,7 @@ You can then run: start(false, true) for { if QUIT { - continue + break } printVersion() start(false, false) diff --git a/pwreset.go b/pwreset.go index 12e26ac..22e9a74 100644 --- a/pwreset.go +++ b/pwreset.go @@ -46,7 +46,7 @@ func (app *appContext) StartPWR() { app.err.Printf("Failed to start password reset daemon: %s", err) } - <-RESTART + waitForRestart() } // PasswordReset represents a passwordreset-xyz.json file generated by Jellyfin. diff --git a/restart.go b/restart.go index 1713619..9c3f782 100644 --- a/restart.go +++ b/restart.go @@ -1,4 +1,4 @@ -// +build !windows +//go:build !windows package main @@ -11,9 +11,10 @@ import ( func (app *appContext) HardRestart() error { defer func() { + quit := make(chan os.Signal, 0) if r := recover(); r != nil { - signal.Notify(app.quit, os.Interrupt) - <-app.quit + signal.Notify(quit, os.Interrupt, syscall.SIGTERM) + <-quit } }() args := os.Args diff --git a/tray.go b/tray.go index a89f108..135a06b 100644 --- a/tray.go +++ b/tray.go @@ -8,6 +8,7 @@ import ( "os" "os/signal" "syscall" + "time" "github.com/getlantern/systray" ) @@ -26,6 +27,8 @@ func onExit() { if RUNNING { QUIT = true RESTART <- true + // Safety Sleep (Ensure shutdown tasks get done) + time.Sleep(time.Second) } os.Remove(SOCK) }