bugfix: Kill the process group, not just the parent process (#328), , thanks @ioqy, @vvrein (#346)

* bugfix: Kill the process group, not just the parent process (#328), thanks @ioqy, @vvrein

* bugfix: Kill the process group, not just the parent process (#328), thanks @ioqy, @vvrein

* bugfix: Kill the process group, not just the parent process (#328), thanks @ioqy, @vvrein
This commit is contained in:
James Read 2024-07-04 01:12:28 +01:00 committed by GitHub
parent fb6aaa52c7
commit 6622a6ded4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 12 deletions

View File

@ -15,9 +15,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"os/exec"
"path" "path"
"runtime"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -355,14 +353,6 @@ func notifyListeners(req *ExecutionRequest) {
} }
} }
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
if runtime.GOOS == "windows" {
return exec.CommandContext(ctx, "cmd", "/C", finalParsedCommand)
}
return exec.CommandContext(ctx, "sh", "-c", finalParsedCommand)
}
func appendErrorToStderr(err error, logEntry *InternalLogEntry) { func appendErrorToStderr(err error, logEntry *InternalLogEntry) {
if err != nil { if err != nil {
logEntry.Output = err.Error() + "\n\n" + logEntry.Output logEntry.Output = err.Error() + "\n\n" + logEntry.Output
@ -422,6 +412,9 @@ func stepExec(req *ExecutionRequest) bool {
appendErrorToStderr(waiterr, req.logEntry) appendErrorToStderr(waiterr, req.logEntry)
if ctx.Err() == context.DeadlineExceeded { if ctx.Err() == context.DeadlineExceeded {
log.Warnf("Command timed out: %v", req.finalParsedCommand)
// The context timeout should kill the process, but let's make sure.
req.executor.Kill(req.logEntry)
req.logEntry.TimedOut = true req.logEntry.TimedOut = true
} }

View File

@ -0,0 +1,25 @@
//go:build !windows
// +build !windows
package executor
import (
"context"
"os/exec"
"syscall"
)
func (e *Executor) Kill(execReq *InternalLogEntry) error {
// A negative PID means to kill the whole process group. This is *nix specific behavior.
return syscall.Kill(-execReq.Process.Pid, syscall.SIGKILL)
}
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
cmd := exec.CommandContext(ctx, "sh", "-c", finalParsedCommand)
// This is to ensure that the process group is killed when the parent process is killed.
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
return cmd
}

View File

@ -0,0 +1,17 @@
//go:build windows
// +build windows
package executor
import (
"context"
"os/exec"
)
func (e *Executor) Kill(execReq *InternalLogEntry) error {
return execReq.Process.Kill()
}
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
return exec.CommandContext(ctx, "cmd", "/C", finalParsedCommand)
}

View File

@ -35,14 +35,14 @@ func (api *oliveTinAPI) KillAction(ctx ctx.Context, req *pb.KillActionRequest) (
ExecutionTrackingId: req.ExecutionTrackingId, ExecutionTrackingId: req.ExecutionTrackingId,
} }
execReq, found := api.executor.Logs[req.ExecutionTrackingId] execReqLogEntry, found := api.executor.Logs[req.ExecutionTrackingId]
ret.Found = found ret.Found = found
if found { if found {
log.Warnf("Killing execution request by tracking ID: %v", req.ExecutionTrackingId) log.Warnf("Killing execution request by tracking ID: %v", req.ExecutionTrackingId)
err := execReq.Process.Kill() err := api.executor.Kill(execReqLogEntry)
if err != nil { if err != nil {
log.Warnf("Killing execution request err: %v", err) log.Warnf("Killing execution request err: %v", err)