mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 00:50:12 +00:00
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
This commit is contained in:
parent
f88f71d933
commit
ad40d7d8a9
4
api.go
4
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
|
||||
}
|
||||
|
@ -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"
|
||||
|
56
main.go
56
main.go
@ -17,6 +17,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
@ -43,6 +44,8 @@ var (
|
||||
SWAGGER *bool
|
||||
QUIT = false
|
||||
RUNNING = false
|
||||
// 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()
|
||||
@ -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,15 +581,10 @@ 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!")
|
||||
|
||||
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 {
|
||||
@ -595,23 +593,26 @@ func start(asDaemon, firstCall bool) {
|
||||
app.info.Println("Server shut down.")
|
||||
return
|
||||
}
|
||||
|
||||
func shutdown() {
|
||||
QUIT = true
|
||||
RESTART <- true
|
||||
// Safety Sleep (Ensure shutdown tasks get done)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
func (app *appContext) shutdown() {
|
||||
app.info.Println("Shutting down...")
|
||||
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)
|
||||
shutdown()
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user