diff --git a/service.go b/service.go index 4794310..35fedc2 100644 --- a/service.go +++ b/service.go @@ -407,7 +407,7 @@ func (s *Service) Kill(id string) error { return nil } -// KillPID terminates a process by operating-system PID. +// KillPID forcefully terminates a process by operating-system PID. // // Example: // @@ -428,7 +428,7 @@ func (s *Service) KillPID(pid int) error { return nil } - if err := syscall.Kill(pid, syscall.SIGTERM); err != nil { + if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { return coreerr.E("Service.KillPID", fmt.Sprintf("failed to signal pid %d", pid), err) } diff --git a/service_test.go b/service_test.go index 5d91099..ba3b0ef 100644 --- a/service_test.go +++ b/service_test.go @@ -2,6 +2,7 @@ package process import ( "context" + "os/exec" "strings" "sync" "testing" @@ -465,6 +466,40 @@ func TestService_Kill(t *testing.T) { }) } +func TestService_KillPID(t *testing.T) { + t.Run("force kills unmanaged process", func(t *testing.T) { + svc, _ := newTestService(t) + + cmd := exec.Command("sleep", "60") + require.NoError(t, cmd.Start()) + + waitCh := make(chan error, 1) + go func() { + waitCh <- cmd.Wait() + }() + + t.Cleanup(func() { + if cmd.ProcessState == nil && cmd.Process != nil { + _ = cmd.Process.Kill() + } + select { + case <-waitCh: + case <-time.After(2 * time.Second): + } + }) + + err := svc.KillPID(cmd.Process.Pid) + require.NoError(t, err) + + select { + case err := <-waitCh: + require.Error(t, err) + case <-time.After(2 * time.Second): + t.Fatal("unmanaged process should have been killed") + } + }) +} + func TestService_Output(t *testing.T) { t.Run("returns captured output", func(t *testing.T) { svc, _ := newTestService(t)