mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +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 {
|
} else {
|
||||||
RESTART <- true
|
RESTART <- true
|
||||||
}
|
}
|
||||||
|
// Safety Sleep (Ensure shutdown tasks get done)
|
||||||
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
app.loadConfig()
|
app.loadConfig()
|
||||||
// Reinitialize password validator on config change, as opposed to every applicable request like in python.
|
// 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 {
|
} else {
|
||||||
RESTART <- true
|
RESTART <- true
|
||||||
}
|
}
|
||||||
|
// Safety Sleep (Ensure shutdown tasks get done)
|
||||||
|
time.Sleep(time.Second)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ func (d *DiscordDaemon) run() {
|
|||||||
defer d.deregisterCommands()
|
defer d.deregisterCommands()
|
||||||
defer d.bot.Close()
|
defer d.bot.Close()
|
||||||
|
|
||||||
d.registerCommands()
|
go d.registerCommands()
|
||||||
|
|
||||||
<-d.ShutdownChannel
|
<-d.ShutdownChannel
|
||||||
d.ShutdownChannel <- "Down"
|
d.ShutdownChannel <- "Down"
|
||||||
|
84
main.go
84
main.go
@ -17,6 +17,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
@ -43,12 +44,14 @@ var (
|
|||||||
SWAGGER *bool
|
SWAGGER *bool
|
||||||
QUIT = false
|
QUIT = false
|
||||||
RUNNING = false
|
RUNNING = false
|
||||||
warning = color.New(color.FgYellow).SprintfFunc()
|
// Used to know how many times to re-broadcast restart signal.
|
||||||
info = color.New(color.FgMagenta).SprintfFunc()
|
RESTARTLISTENERCOUNT = 0
|
||||||
hiwhite = color.New(color.FgHiWhite).SprintfFunc()
|
warning = color.New(color.FgYellow).SprintfFunc()
|
||||||
white = color.New(color.FgWhite).SprintfFunc()
|
info = color.New(color.FgMagenta).SprintfFunc()
|
||||||
version string
|
hiwhite = color.New(color.FgHiWhite).SprintfFunc()
|
||||||
commit string
|
white = color.New(color.FgWhite).SprintfFunc()
|
||||||
|
version string
|
||||||
|
commit string
|
||||||
)
|
)
|
||||||
|
|
||||||
var temp = func() string {
|
var temp = func() string {
|
||||||
@ -102,7 +105,6 @@ type appContext struct {
|
|||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
version string
|
version string
|
||||||
quit chan os.Signal
|
|
||||||
URLBase string
|
URLBase string
|
||||||
updater *Updater
|
updater *Updater
|
||||||
newUpdate bool // Whether whatever's in update is new.
|
newUpdate bool // Whether whatever's in update is new.
|
||||||
@ -152,6 +154,7 @@ func test(app *appContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func start(asDaemon, firstCall bool) {
|
func start(asDaemon, firstCall bool) {
|
||||||
|
RESTARTLISTENERCOUNT = 0
|
||||||
RUNNING = true
|
RUNNING = true
|
||||||
defer func() { RUNNING = false }()
|
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)
|
app.err.Fatalf("Couldn't establish socket connection at %s\n", SOCK)
|
||||||
}
|
}
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, os.Interrupt)
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
go func() {
|
go func() {
|
||||||
<-c
|
<-c
|
||||||
os.Remove(SOCK)
|
os.Remove(SOCK)
|
||||||
@ -578,40 +581,38 @@ func start(asDaemon, firstCall bool) {
|
|||||||
} else {
|
} else {
|
||||||
app.info.Printf("Loaded @ %s", address)
|
app.info.Printf("Loaded @ %s", address)
|
||||||
}
|
}
|
||||||
app.quit = make(chan os.Signal)
|
|
||||||
signal.Notify(app.quit, os.Interrupt)
|
waitForRestart()
|
||||||
go func() {
|
|
||||||
for range app.quit {
|
app.info.Printf("Restart/Quit signal received, give me a second!")
|
||||||
app.shutdown()
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
}
|
defer cancel()
|
||||||
}()
|
if err := SRV.Shutdown(ctx); err != nil {
|
||||||
for range RESTART {
|
app.err.Fatalf("Server shutdown error: %s", err)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
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() {
|
func (app *appContext) shutdown() {
|
||||||
app.info.Println("Shutting down...")
|
app.info.Println("Shutting down...")
|
||||||
QUIT = true
|
shutdown()
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
TEST = true
|
||||||
}
|
}
|
||||||
loadFilesystems()
|
loadFilesystems()
|
||||||
|
|
||||||
|
quit := make(chan os.Signal, 0)
|
||||||
|
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
|
||||||
|
// defer close(quit)
|
||||||
|
go func() {
|
||||||
|
<-quit
|
||||||
|
shutdown()
|
||||||
|
}()
|
||||||
|
|
||||||
if flagPassed("start") {
|
if flagPassed("start") {
|
||||||
args := []string{}
|
args := []string{}
|
||||||
for i, f := range os.Args {
|
for i, f := range os.Args {
|
||||||
@ -760,7 +770,7 @@ You can then run:
|
|||||||
start(false, true)
|
start(false, true)
|
||||||
for {
|
for {
|
||||||
if QUIT {
|
if QUIT {
|
||||||
continue
|
break
|
||||||
}
|
}
|
||||||
printVersion()
|
printVersion()
|
||||||
start(false, false)
|
start(false, false)
|
||||||
|
@ -46,7 +46,7 @@ func (app *appContext) StartPWR() {
|
|||||||
app.err.Printf("Failed to start password reset daemon: %s", err)
|
app.err.Printf("Failed to start password reset daemon: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-RESTART
|
waitForRestart()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PasswordReset represents a passwordreset-xyz.json file generated by Jellyfin.
|
// PasswordReset represents a passwordreset-xyz.json file generated by Jellyfin.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// +build !windows
|
//go:build !windows
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -11,9 +11,10 @@ import (
|
|||||||
|
|
||||||
func (app *appContext) HardRestart() error {
|
func (app *appContext) HardRestart() error {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
quit := make(chan os.Signal, 0)
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
signal.Notify(app.quit, os.Interrupt)
|
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
|
||||||
<-app.quit
|
<-quit
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
args := os.Args
|
args := os.Args
|
||||||
|
3
tray.go
3
tray.go
@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/getlantern/systray"
|
"github.com/getlantern/systray"
|
||||||
)
|
)
|
||||||
@ -26,6 +27,8 @@ func onExit() {
|
|||||||
if RUNNING {
|
if RUNNING {
|
||||||
QUIT = true
|
QUIT = true
|
||||||
RESTART <- true
|
RESTART <- true
|
||||||
|
// Safety Sleep (Ensure shutdown tasks get done)
|
||||||
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
os.Remove(SOCK)
|
os.Remove(SOCK)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user