diff --git a/process.go b/process.go index ceb993d..30c7e3d 100644 --- a/process.go +++ b/process.go @@ -269,6 +269,10 @@ func (p *ManagedProcess) Signal(sig os.Signal) error { return cmd.Process.Signal(sig) } + if sysSig == 0 { + return syscall.Kill(-cmd.Process.Pid, 0) + } + if err := syscall.Kill(-cmd.Process.Pid, sysSig); err != nil { return err } diff --git a/process_test.go b/process_test.go index 1a4f037..596bc31 100644 --- a/process_test.go +++ b/process_test.go @@ -3,6 +3,7 @@ package process import ( "context" "os" + "syscall" "testing" "time" @@ -300,6 +301,33 @@ func TestProcess_Signal(t *testing.T) { t.Fatal("process group should have been terminated by signal") } }) + + t.Run("signal zero only probes process group liveness", func(t *testing.T) { + svc, _ := newTestService(t) + + proc, err := svc.StartWithOptions(context.Background(), RunOptions{ + Command: "sh", + Args: []string{"-c", "sleep 60 & wait"}, + Detach: true, + KillGroup: true, + }) + require.NoError(t, err) + + err = proc.Signal(syscall.Signal(0)) + assert.NoError(t, err) + + time.Sleep(300 * time.Millisecond) + assert.True(t, proc.IsRunning()) + + err = proc.Kill() + assert.NoError(t, err) + + select { + case <-proc.Done(): + case <-time.After(5 * time.Second): + t.Fatal("process group should have been killed for cleanup") + } + }) } func TestProcess_CloseStdin(t *testing.T) { diff --git a/service_test.go b/service_test.go index 9663435..0d98959 100644 --- a/service_test.go +++ b/service_test.go @@ -927,6 +927,34 @@ func TestService_OnStartup(t *testing.T) { <-proc.Done() }) + t.Run("signal zero does not kill process groups", func(t *testing.T) { + svc, c := newTestService(t) + + err := svc.OnStartup(context.Background()) + require.NoError(t, err) + + proc, err := svc.StartWithOptions(context.Background(), RunOptions{ + Command: "sh", + Args: []string{"-c", "sleep 60 & wait"}, + Detach: true, + KillGroup: true, + }) + require.NoError(t, err) + + result := c.PERFORM(TaskProcessSignal{ + ID: proc.ID, + Signal: syscall.Signal(0), + }) + require.True(t, result.OK) + + time.Sleep(300 * time.Millisecond) + assert.True(t, proc.IsRunning()) + + err = proc.Kill() + require.NoError(t, err) + <-proc.Done() + }) + t.Run("registers process.wait task", func(t *testing.T) { svc, c := newTestService(t)