Add graceful service termination

This commit is contained in:
EnumDev 2025-02-23 18:30:03 +02:00
parent a31c319627
commit b04fd51245
2 changed files with 65 additions and 53 deletions

View File

@ -10,6 +10,7 @@ import (
"path"
"strconv"
"syscall"
"time"
)
// Build-time variables
@ -94,6 +95,39 @@ func startServiceManager() {
fmt.Println("Done")
}
func stopServiceManager() {
fmt.Println("Stopping service manager... ")
err := syscall.Kill(serviceManagerPid, syscall.SIGTERM)
if err != nil {
log.Println("Could not stop service manager!")
}
// Check if service manager has stopped gracefully, otherwise send sigkill on timeout
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
log.Println("Could not stop service manager!")
err := syscall.Kill(serviceManagerPid, syscall.SIGKILL)
if err != nil {
log.Println("Could not stop service manager!")
}
case <-ticker.C:
p, err := os.FindProcess(serviceManagerPid)
if err != nil {
break
}
err = p.Signal(syscall.Signal(0))
if err != nil {
break
}
}
fmt.Print("Done.")
}
func waitZombieProcesses() {
for {
if wpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil); wpid <= 0 {
@ -141,17 +175,13 @@ func catchSignals() {
func shutdownSystem() {
fmt.Println("Shutting down...")
fmt.Println("Stopping services... ")
err := syscall.Kill(serviceManagerPid, syscall.SIGTERM)
if err != nil {
log.Println("Could not stop service manager!")
panic(err)
}
fmt.Print("Done.")
stopServiceManager()
fmt.Println("Syncing disks...")
syscall.Sync()
fmt.Println("Sending shutdown syscall...")
syscall.Sync()
err = syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF)
err := syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF)
if err != nil {
panic(err)
}
@ -160,17 +190,13 @@ func shutdownSystem() {
func rebootSystem() {
fmt.Println("Rebooting...")
fmt.Println("Stopping service manager... ")
err := syscall.Kill(serviceManagerPid, syscall.SIGTERM)
if err != nil {
log.Println("Could not stop service manager!")
panic(err)
}
fmt.Print("Done.")
stopServiceManager()
fmt.Println("Syncing disks...")
syscall.Sync()
fmt.Println("Sending reboot syscall...")
syscall.Sync()
err = syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART)
err := syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART)
if err != nil {
panic(err)
}

View File

@ -14,6 +14,7 @@ import (
"strconv"
"strings"
"syscall"
"time"
)
type EnitServiceState uint8
@ -229,7 +230,7 @@ func (service *EnitService) StartService() error {
return nil
}
cmd := exec.Command("/bin/sh", "-c", service.StartCmd)
cmd := exec.Command("/bin/sh", "-c", "exec "+service.StartCmd)
if err := cmd.Start(); err != nil {
return err
}
@ -271,10 +272,28 @@ func (service *EnitService) StopService() error {
return nil
}
go func() { service.stopChannel <- true }()
err := service.GetProcess().Signal(syscall.SIGTERM)
if err != nil {
return err
}
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
err := service.GetProcess().Kill()
if err != nil {
return err
}
case <-ticker.C:
if service.GetProcess() == nil {
break
}
}
} else {
cmd := exec.Command("/bin/sh", "-c", service.StopCmd)
if err := cmd.Run(); err != nil {
@ -307,39 +326,6 @@ func (service *EnitService) RestartService() error {
return nil
}
func checkForServiceCommand() {
for _, service := range Services {
if _, err := os.Stat(path.Join(service.ServiceRunPath, "start")); err == nil {
err := service.StartService()
if err != nil {
return
}
err = os.Remove(path.Join(service.ServiceRunPath, "start"))
if err != nil {
return
}
} else if _, err := os.Stat(path.Join(service.ServiceRunPath, "stop")); err == nil {
err := service.StopService()
if err != nil {
return
}
err = os.Remove(path.Join(service.ServiceRunPath, "stop"))
if err != nil {
return
}
} else if _, err := os.Stat(path.Join(service.ServiceRunPath, "restart")); err == nil {
err := service.RestartService()
if err != nil {
return
}
err = os.Remove(path.Join(service.ServiceRunPath, "restart"))
if err != nil {
return
}
}
}
}
func listenToSocket() {
conn, err := socket.Accept()
if err != nil {