fix: use SIGTERM, then SIGKILL to avoid zombies #266

This commit is contained in:
seriousm4x
2023-10-19 18:47:14 +02:00
parent a4ab575eb3
commit 2f3ad2fdcb
3 changed files with 16 additions and 13 deletions

View File

@@ -31,9 +31,10 @@ func ShutdownDevice(device *models.Record) error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cmd := exec.CommandContext(ctx, shell, shell_arg, shutdown_cmd)
SetProcessAttributes(cmd)
logger.Debug.Println(cmd)
var stderr bytes.Buffer
cmd.Stderr = &stderr
@@ -56,7 +57,6 @@ func ShutdownDevice(device *models.Record) error {
if err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
cancel()
return fmt.Errorf("%s not offline after 2 minutes", device.GetString("name"))
}
isOnline := PingDevice(device)
@@ -64,7 +64,6 @@ func ShutdownDevice(device *models.Record) error {
if err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
cancel()
return nil
}
case err := <-done:
@@ -72,7 +71,6 @@ func ShutdownDevice(device *models.Record) error {
if err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
cancel()
return fmt.Errorf("%s", stderr.String())
}
}

View File

@@ -4,9 +4,8 @@ import (
"os"
"os/exec"
"golang.org/x/sys/unix"
"github.com/seriousm4x/upsnap/logger"
"golang.org/x/sys/unix"
)
// Set platform specifiy custom process attributes
@@ -16,10 +15,18 @@ func SetProcessAttributes(cmd *exec.Cmd) {
// Kills child processes on Linux. Windows doesn't provide a direct way to kill child processes, so we kill just the main process.
func KillProcess(process *os.Process) error {
logger.Warning.Println("Your shutdown cmd didn't finish in 2 minutes. It will be killed.")
pgid, err := unix.Getpgid(process.Pid)
logger.Debug.Println(pgid)
if err != nil {
return err
}
return unix.Kill(-pgid, unix.SIGKILL)
err = unix.Kill(-pgid, unix.SIGTERM)
if err != nil {
return unix.Kill(-pgid, unix.SIGKILL)
}
_, err = process.Wait()
return err
}

View File

@@ -1,4 +1,5 @@
//go:build !linux
//go:build windows
// +build windows
package networking
@@ -12,8 +13,5 @@ func SetProcessAttributes(cmd *exec.Cmd) {}
// Kills child processes on Linux. Windows doesn't provide a direct way to kill child processes, so we kill just the main process.
func KillProcess(process *os.Process) error {
if err := process.Kill(); err != nil {
return err
}
return nil
return windows.GenerateConsoleCtrlEvent(windows.CTRL_BREAK_EVENT, uint32(process.Pid))
}