diff --git a/cmd/entrypoint/runner.go b/cmd/entrypoint/runner.go index 9d89b4d2c19..a8082dfa533 100644 --- a/cmd/entrypoint/runner.go +++ b/cmd/entrypoint/runner.go @@ -3,6 +3,8 @@ package main import ( "os" "os/exec" + "os/signal" + "syscall" "github.com/tektoncd/pipeline/pkg/entrypoint" ) @@ -11,22 +13,52 @@ import ( // stdout/stderr are collected -- needs e2e tests. // realRunner actually runs commands. -type realRunner struct{} +type realRunner struct { + signals chan os.Signal +} var _ entrypoint.Runner = (*realRunner)(nil) -func (*realRunner) Run(args ...string) error { +func (rr *realRunner) Run(args ...string) error { if len(args) == 0 { return nil } name, args := args[0], args[1:] + // Receive system signals on "rr.signals" + if rr.signals == nil { + rr.signals = make(chan os.Signal, 1) + } + defer close(rr.signals) + signal.Notify(rr.signals) + defer signal.Reset() + cmd := exec.Command(name, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + // dedicated PID group used to forward signals to + // main process and all children + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + // Start defined command + if err := cmd.Start(); err != nil { + return err + } - if err := cmd.Run(); err != nil { + // Goroutine for signals forwarding + go func() { + for s := range rr.signals { + // Forward signal to main process and all children + if s != syscall.SIGCHLD { + _ = syscall.Kill(-cmd.Process.Pid, s.(syscall.Signal)) + } + } + }() + + // Wait for command to exit + if err := cmd.Wait(); err != nil { return err } + return nil } diff --git a/cmd/entrypoint/runner_test.go b/cmd/entrypoint/runner_test.go new file mode 100644 index 00000000000..fe930eb32a7 --- /dev/null +++ b/cmd/entrypoint/runner_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "os" + "syscall" + "testing" +) + +func TestRealRunnerSignalForwarding(t *testing.T) { + rr := realRunner{} + rr.signals = make(chan os.Signal, 1) + rr.signals <- syscall.SIGINT + if err := rr.Run("sleep", "3600"); err.Error() == "signal: interrupt" { + t.Logf("SIGINT forwarded to Entrypoint") + } else { + t.Fatalf("Unexpected error received: %v", err) + } +}