Add graceful service termination
This commit is contained in:
parent
a31c319627
commit
b04fd51245
@ -10,6 +10,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Build-time variables
|
// Build-time variables
|
||||||
@ -94,6 +95,39 @@ func startServiceManager() {
|
|||||||
fmt.Println("Done")
|
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() {
|
func waitZombieProcesses() {
|
||||||
for {
|
for {
|
||||||
if wpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil); wpid <= 0 {
|
if wpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil); wpid <= 0 {
|
||||||
@ -141,17 +175,13 @@ func catchSignals() {
|
|||||||
func shutdownSystem() {
|
func shutdownSystem() {
|
||||||
fmt.Println("Shutting down...")
|
fmt.Println("Shutting down...")
|
||||||
|
|
||||||
fmt.Println("Stopping services... ")
|
stopServiceManager()
|
||||||
err := syscall.Kill(serviceManagerPid, syscall.SIGTERM)
|
|
||||||
if err != nil {
|
fmt.Println("Syncing disks...")
|
||||||
log.Println("Could not stop service manager!")
|
syscall.Sync()
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Print("Done.")
|
|
||||||
|
|
||||||
fmt.Println("Sending shutdown syscall...")
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -160,17 +190,13 @@ func shutdownSystem() {
|
|||||||
func rebootSystem() {
|
func rebootSystem() {
|
||||||
fmt.Println("Rebooting...")
|
fmt.Println("Rebooting...")
|
||||||
|
|
||||||
fmt.Println("Stopping service manager... ")
|
stopServiceManager()
|
||||||
err := syscall.Kill(serviceManagerPid, syscall.SIGTERM)
|
|
||||||
if err != nil {
|
fmt.Println("Syncing disks...")
|
||||||
log.Println("Could not stop service manager!")
|
syscall.Sync()
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Print("Done.")
|
|
||||||
|
|
||||||
fmt.Println("Sending reboot syscall...")
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EnitServiceState uint8
|
type EnitServiceState uint8
|
||||||
@ -229,7 +230,7 @@ func (service *EnitService) StartService() error {
|
|||||||
return nil
|
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 {
|
if err := cmd.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -271,10 +272,28 @@ func (service *EnitService) StopService() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
go func() { service.stopChannel <- true }()
|
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()
|
err := service.GetProcess().Kill()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case <-ticker.C:
|
||||||
|
if service.GetProcess() == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cmd := exec.Command("/bin/sh", "-c", service.StopCmd)
|
cmd := exec.Command("/bin/sh", "-c", service.StopCmd)
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
@ -307,39 +326,6 @@ func (service *EnitService) RestartService() error {
|
|||||||
return nil
|
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() {
|
func listenToSocket() {
|
||||||
conn, err := socket.Accept()
|
conn, err := socket.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user