diff --git a/cmd/clusterctl/cmd/daemon_restart.go b/cmd/clusterctl/cmd/daemon_restart.go index 0a12ba5..e1a83e2 100644 --- a/cmd/clusterctl/cmd/daemon_restart.go +++ b/cmd/clusterctl/cmd/daemon_restart.go @@ -10,8 +10,11 @@ package cmd import ( - "fmt" + "os" + "strconv" + "syscall" + "git.staur.ca/stobbsm/clustvirt/lib/log" "github.com/spf13/cobra" ) @@ -22,7 +25,49 @@ var restartCmd = &cobra.Command{ Long: `Some configuration requires the daemon to restart itself. This command sends the SIGUSR2 signal, telling the daemon to restart`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("restart called") + log.Info("cmd.daemon.restart"). + Msg("restarting daemon") + sPid, err := os.ReadFile(`/run/clustvirt.pid`) + if err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Msg("unable to restart") + os.Exit(1) + } + pid, err := strconv.Atoi(string(sPid)) + if err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Msg("unable to restart") + os.Exit(1) + } + proc, err := os.FindProcess(pid) + if err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Msg("unable to restart") + os.Exit(1) + } + // make sure the process found is currently alive + if err = proc.Signal(syscall.Signal(0)); err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Int("PID", pid). + Msg("expected process doesn't seem to exist") + } + if err = proc.Signal(syscall.SIGUSR2); err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Msg("unable to restart") + os.Exit(1) + } + ps, err := proc.Wait() + if err != nil { + log.Error("cmd.daemon.restart"). + Err(err). + Msg("unable to restart") + os.Exit(1) + } }, } diff --git a/daemon/control.go b/daemon/control.go new file mode 100644 index 0000000..be2d569 --- /dev/null +++ b/daemon/control.go @@ -0,0 +1,18 @@ +package daemon + +import ( + "fmt" + "os" + + "git.staur.ca/stobbsm/clustvirt/lib/log" +) + +func Start() { + pid := pid() + if err := os.WriteFile(PIDFile, []byte(fmt.Sprint(pid)), 0666); err != nil { + log.Error("daemon.Start"). + Err(err). + Send() + os.Exit(1) + } +} diff --git a/daemon/main.go b/daemon/main.go index 64ffaff..b798264 100644 --- a/daemon/main.go +++ b/daemon/main.go @@ -1,8 +1,9 @@ package daemon import ( - "fmt" + "context" "os" + "syscall" "git.staur.ca/stobbsm/clustvirt/lib/log" ) @@ -17,16 +18,44 @@ func init() { PIDFile = RunPath + `clustvirt.pid` } -func Start() { - pid := pid() - if err := os.WriteFile(PIDFile, []byte(fmt.Sprint(pid)), 0666); err != nil { - log.Error("daemon.Start"). - Err(err). - Send() - os.Exit(1) - } -} - func pid() int { return os.Getpid() } + +func sigHandler(c <-chan os.Signal) context.Context { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + for { + sig := <-c + switch sig { + case syscall.SIGTERM: + log.Info("daemon.sigHandler"). + Str("signal", "SIGTERM"). + Msg("stopping clustvirt gracefully") + cancel() + <-ctx.Done() + os.Exit(0) + case syscall.SIGKILL: + log.Warn("daemon.sigHandler"). + Str("signal", "SIGKILL"). + Msg("killed. avenge me...") + os.Exit(1) + case syscall.SIGUSR1: + log.Info("daemon.sigHandler"). + Str("signal", "SIGUSR1"). + Msg("reloading configuration") + // TODO: Reload the application configuration here + case syscall.SIGUSR2: + log.Info("daemon.sigHandler"). + Str("signal", "SIGUSR2"). + Msg("restarting...") + // TODO: implement restart logic here + default: + log.Warn("daemon.sigHandler"). + Str("signal", sig.String()). + Msg("unhandled signal recieved") + } + } + }() + return ctx +}