Skip to content

Commit a44deac

Browse files
committed
feat: support for --sig-proxy in run
Signed-off-by: CodeChanning <[email protected]>
1 parent b63820a commit a44deac

File tree

7 files changed

+112
-3
lines changed

7 files changed

+112
-3
lines changed

cmd/nerdctl/container_run.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func setCreateFlags(cmd *cobra.Command) {
7979
cmd.Flags().Bool("help", false, "show help")
8080

8181
cmd.Flags().BoolP("tty", "t", false, "Allocate a pseudo-TTY")
82+
cmd.Flags().Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
8283
cmd.Flags().BoolP("interactive", "i", false, "Keep STDIN open even if not attached")
8384
cmd.Flags().String("restart", "no", `Restart policy to apply when a container exits (implemented values: "no"|"always|on-failure:n|unless-stopped")`)
8485
cmd.RegisterFlagCompletionFunc("restart", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
@@ -287,6 +288,10 @@ func processCreateCommandFlagsInRun(cmd *cobra.Command) (opt types.ContainerCrea
287288

288289
opt.InRun = true
289290

291+
opt.SigProxy, err = cmd.Flags().GetBool("sig-proxy")
292+
if err != nil {
293+
return
294+
}
290295
opt.Interactive, err = cmd.Flags().GetBool("interactive")
291296
if err != nil {
292297
return
@@ -394,8 +399,10 @@ func runAction(cmd *cobra.Command, args []string) error {
394399
log.L.WithError(err).Error("console resize")
395400
}
396401
} else {
397-
sigC := signalutil.ForwardAllSignals(ctx, task)
398-
defer signalutil.StopCatch(sigC)
402+
if createOpt.SigProxy {
403+
sigC := signalutil.ForwardAllSignals(ctx, task)
404+
defer signalutil.StopCatch(sigC)
405+
}
399406
}
400407

401408
statusC, err := task.Wait(ctx)

cmd/nerdctl/container_run_linux_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"runtime"
3030
"strconv"
3131
"strings"
32+
"syscall"
3233
"testing"
3334
"time"
3435

@@ -311,6 +312,80 @@ func TestRunTTY(t *testing.T) {
311312
assert.Equal(t, 0, res.ExitCode, res.Combined())
312313
}
313314

315+
func runSigProxy(t *testing.T, args ...string) (string, bool, bool) {
316+
t.Parallel()
317+
base := testutil.NewBase(t)
318+
testContainerName := testutil.Identifier(t)
319+
defer base.Cmd("rm", "-f", testContainerName).Run()
320+
321+
fullArgs := []string{"run"}
322+
fullArgs = append(fullArgs, args...)
323+
fullArgs = append(fullArgs,
324+
"--name",
325+
testContainerName,
326+
testutil.CommonImage,
327+
"sh",
328+
"-c",
329+
testutil.SigProxyTestScript,
330+
)
331+
332+
result := base.Cmd(fullArgs...).Start()
333+
process := result.Cmd.Process
334+
335+
// Waits until we reach the trap command in the shell script, then sends SIGINT.
336+
time.Sleep(3 * time.Second)
337+
syscall.Kill(process.Pid, syscall.SIGINT)
338+
339+
// Waits until SIGINT is sent and responded to, then kills process to avoid timeout
340+
time.Sleep(3 * time.Second)
341+
process.Kill()
342+
343+
sigIntRecieved := strings.Contains(result.Stdout(), testutil.SigProxyTrueOut)
344+
timedOut := strings.Contains(result.Stdout(), testutil.SigProxyTimeoutMsg)
345+
346+
return result.Stdout(), sigIntRecieved, timedOut
347+
}
348+
349+
func TestRunSigProxy(t *testing.T) {
350+
351+
type testCase struct {
352+
name string
353+
args []string
354+
want bool
355+
expectedOut string
356+
}
357+
testCases := []testCase{
358+
{
359+
name: "SigProxyDefault",
360+
args: []string{},
361+
want: true,
362+
expectedOut: testutil.SigProxyTrueOut,
363+
},
364+
{
365+
name: "SigProxyTrue",
366+
args: []string{"--sig-proxy=true"},
367+
want: true,
368+
expectedOut: testutil.SigProxyTrueOut,
369+
},
370+
{
371+
name: "SigProxyFalse",
372+
args: []string{"--sig-proxy=false"},
373+
want: false,
374+
expectedOut: "",
375+
},
376+
}
377+
378+
for _, tc := range testCases {
379+
tc := tc
380+
t.Run(tc.name, func(t *testing.T) {
381+
stdout, sigIntRecieved, timedOut := runSigProxy(t, tc.args...)
382+
errorMsg := fmt.Sprintf("%s failed;\nExpected: '%s'\nActual: '%s'", tc.name, tc.expectedOut, stdout)
383+
assert.Equal(t, false, timedOut, errorMsg)
384+
assert.Equal(t, tc.want, sigIntRecieved, errorMsg)
385+
})
386+
}
387+
}
388+
314389
func TestRunWithFluentdLogDriver(t *testing.T) {
315390
if runtime.GOOS == "windows" {
316391
t.Skip("fluentd log driver is not yet implemented on Windows")

docs/command-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ IPFS flags:
388388
Unimplemented `docker run` flags:
389389
`--attach`, `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`,
390390
`--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--isolation`, `--no-healthcheck`,
391-
`--link*`, `--publish-all`, `--sig-proxy`, `--storage-opt`,
391+
`--link*`, `--publish-all`, `--storage-opt`,
392392
`--userns`, `--volume-driver`
393393

394394
### :whale: :blue_square: nerdctl exec

pkg/api/types/container_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type ContainerCreateOptions struct {
6262
Interactive bool
6363
// TTY specifies whether to allocate a pseudo-TTY for the container
6464
TTY bool
65+
// SigProxy specifies whether to proxy all received signals to the process
66+
SigProxy bool
6567
// Detach runs container in background and print container ID
6668
Detach bool
6769
// The key sequence for detaching a container.

pkg/composer/run.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type RunOptions struct {
4545
Detach bool
4646
NoDeps bool
4747
Tty bool
48+
SigProxy bool
4849
Interactive bool
4950
Rm bool
5051
User string

pkg/testutil/testutil.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ func (c *Cmd) runIfNecessary() *icmd.Result {
366366
return c.runResult
367367
}
368368

369+
func (c *Cmd) Start() *icmd.Result {
370+
c.Base.T.Helper()
371+
return icmd.StartCmd(c.Cmd)
372+
}
373+
369374
func (c *Cmd) CmdOption(cmdOptions ...func(*Cmd)) *Cmd {
370375
for _, opt := range cmdOptions {
371376
opt(c)

pkg/testutil/testutil_linux.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ var (
5656
// It should be "connection refused" as per the TCP RFC.
5757
// https://www.rfc-editor.org/rfc/rfc793
5858
ExpectedConnectionRefusedError = "connection refused"
59+
60+
SigProxyTrueOut = "received SIGINT"
61+
SigProxyTimeoutMsg = "Timed Out; No signal received"
62+
SigProxyTestScript = `#!/bin/sh
63+
set -eu
64+
65+
sig_msg () {
66+
printf "` + SigProxyTrueOut + `"
67+
end
68+
}
69+
70+
trap sig_msg INT
71+
timeout=0
72+
while [ $timeout -ne 10 ]; do
73+
timeout=$((timeout+1))
74+
sleep 1
75+
done
76+
printf "` + SigProxyTimeoutMsg + `"
77+
end`
5978
)
6079

6180
const (

0 commit comments

Comments
 (0)