mirror of
https://github.com/Xevion/HATray.git
synced 2025-12-06 01:15:11 -06:00
feat: update linux service layer implementation, remove SIGUSR1+2 handlers, simpler unified heartbeat/signal routine
This commit is contained in:
@@ -41,50 +41,53 @@ func (s *linuxService) Run() error {
|
|||||||
|
|
||||||
// Setup signal handling for systemd
|
// Setup signal handling for systemd
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGUSR2)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
// Notify systemd that we are ready
|
// Setup heartbeat to systemd
|
||||||
daemon.SdNotify(false, "READY=1")
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
daemon.SdNotify(false, "STATUS=HATray running\n")
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
// Start the service (backgrounded so that the service can still respond to systemd signals, the app layer is still designed for concurrency)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
if err := s.app.Resume(); err != nil {
|
||||||
sig := <-sigs
|
s.logger.Error("failed to start (resume) app layer", "error", err)
|
||||||
|
|
||||||
|
// TODO: This has no true error handling, retry mechanism, or timeout mechanism. If this fails, then the service will be stuck in the 'StartPending' state.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify systemd that we are ready (and running)
|
||||||
|
daemon.SdNotify(false, "READY=1")
|
||||||
|
daemon.SdNotify(false, "STATUS=HATray running\n")
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
daemon.SdNotify(false, "WATCHDOG=1")
|
||||||
|
s.logger.Debug("heartbeat") // TODO: add more detailed status information here
|
||||||
|
case sig := <-sigs:
|
||||||
s.logger.Info("signal received", "signal", sig)
|
s.logger.Info("signal received", "signal", sig)
|
||||||
|
|
||||||
switch sig {
|
switch sig {
|
||||||
case syscall.SIGINT, syscall.SIGTERM:
|
case syscall.SIGINT, syscall.SIGTERM:
|
||||||
daemon.SdNotify(false, "STOPPING=1")
|
daemon.SdNotify(false, "STOPPING=1")
|
||||||
s.logger.Info("stopping service")
|
s.logger.Info("stopping service")
|
||||||
s.app.Stop()
|
|
||||||
close(done)
|
if err := s.app.Pause(); err != nil {
|
||||||
return
|
s.logger.Error("failed to pause app layer", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil // exit the service
|
||||||
case syscall.SIGHUP:
|
case syscall.SIGHUP:
|
||||||
s.logger.Info("reloading service")
|
s.logger.Info("reloading service")
|
||||||
daemon.SdNotify(false, "RELOADING=1")
|
daemon.SdNotify(false, "RELOADING=1")
|
||||||
s.app.Reload()
|
|
||||||
daemon.SdNotify(false, "READY=1")
|
|
||||||
case syscall.SIGUSR1:
|
|
||||||
s.logger.Info("pausing service")
|
|
||||||
s.app.Pause()
|
|
||||||
case syscall.SIGUSR2:
|
|
||||||
s.logger.Info("resuming service")
|
|
||||||
s.app.Resume()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Main loop: heartbeat to systemd
|
if err := s.app.Reload(); err != nil {
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
s.logger.Error("failed to reload app layer", "error", err)
|
||||||
defer ticker.Stop()
|
}
|
||||||
for {
|
|
||||||
select {
|
daemon.SdNotify(false, "READY=1")
|
||||||
case <-done:
|
}
|
||||||
s.logger.Info("service stopped")
|
|
||||||
return nil
|
|
||||||
case <-ticker.C:
|
|
||||||
daemon.SdNotify(false, "WATCHDOG=1")
|
|
||||||
s.logger.Debug("heartbeat")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user