fix bugs with restarts/interrupts

The password reset daemon wasn't being closed on restarts, so an extra
pwr would be sent w/ every restart. Restarts & Interrupts (Ctrl-C)
rarely worked, as there were multiple listeners to the "RESTART"
channel, and I didn't know the message was consumed by whoever got it
first, meaning if the main thread didn't get it first, the app wouldn't
quit. Listeners are now registered, and the restart message is
re-broadcasted until everyone's got it.

Fixes #264
pull/270/head
Harvey Tindall 1 year ago
parent f88f71d933
commit ad40d7d8a9
No known key found for this signature in database
GPG Key ID: BBC65952848FB1A2

@ -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
}

@ -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"

@ -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)

@ -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.

@ -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

@ -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)
}

Loading…
Cancel
Save