mirror of
https://github.com/Xevion/HATray.git
synced 2025-12-05 23:15:09 -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
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGUSR2)
|
||||
done := make(chan struct{})
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||
|
||||
// Notify systemd that we are ready
|
||||
daemon.SdNotify(false, "READY=1")
|
||||
daemon.SdNotify(false, "STATUS=HATray running\n")
|
||||
// Setup heartbeat to systemd
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
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() {
|
||||
for {
|
||||
sig := <-sigs
|
||||
if err := s.app.Resume(); err != nil {
|
||||
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)
|
||||
|
||||
switch sig {
|
||||
case syscall.SIGINT, syscall.SIGTERM:
|
||||
daemon.SdNotify(false, "STOPPING=1")
|
||||
s.logger.Info("stopping service")
|
||||
s.app.Stop()
|
||||
close(done)
|
||||
return
|
||||
|
||||
if err := s.app.Pause(); err != nil {
|
||||
s.logger.Error("failed to pause app layer", "error", err)
|
||||
}
|
||||
|
||||
return nil // exit the service
|
||||
case syscall.SIGHUP:
|
||||
s.logger.Info("reloading service")
|
||||
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
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
s.logger.Info("service stopped")
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
daemon.SdNotify(false, "WATCHDOG=1")
|
||||
s.logger.Debug("heartbeat")
|
||||
if err := s.app.Reload(); err != nil {
|
||||
s.logger.Error("failed to reload app layer", "error", err)
|
||||
}
|
||||
|
||||
daemon.SdNotify(false, "READY=1")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user