diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-10-17 12:27:58 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-10-17 12:29:05 -0700 |
commit | 4e6f0892c96c374b1abcf5c39b75ba52d98c97f8 (patch) | |
tree | cb21538ad26a50ff61086d55c1bef36d5026e4c0 /runsc/test/integration | |
parent | 578fe5a50dcf8e104b6bce3802987b0f8c069ade (diff) |
runsc: Support job control signals for the root container.
Now containers run with "docker run -it" support control characters like ^C and
^Z.
This required refactoring our signal handling a bit. Signals delivered to the
"runsc boot" process are turned into loader.Signal calls with the appropriate
delivery mode. Previously they were always sent directly to PID 1.
PiperOrigin-RevId: 217566770
Change-Id: I5b7220d9a0f2b591a56335479454a200c6de8732
Diffstat (limited to 'runsc/test/integration')
-rw-r--r-- | runsc/test/integration/exec_test.go | 2 | ||||
-rw-r--r-- | runsc/test/integration/integration_test.go | 48 |
2 files changed, 49 insertions, 1 deletions
diff --git a/runsc/test/integration/exec_test.go b/runsc/test/integration/exec_test.go index d08140ad3..3cac674d0 100644 --- a/runsc/test/integration/exec_test.go +++ b/runsc/test/integration/exec_test.go @@ -66,7 +66,7 @@ func TestExecJobControl(t *testing.T) { if err := testutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("exec-test") + d := testutil.MakeDocker("exec-job-control-test") // Start the container. if err := d.Run("alpine", "sleep", "1000"); err != nil { diff --git a/runsc/test/integration/integration_test.go b/runsc/test/integration/integration_test.go index b7d07309d..536bb17e0 100644 --- a/runsc/test/integration/integration_test.go +++ b/runsc/test/integration/integration_test.go @@ -28,6 +28,7 @@ import ( "os" "strconv" "strings" + "syscall" "testing" "time" @@ -231,6 +232,53 @@ func TestNumCPU(t *testing.T) { } } +// TestJobControl tests that job control characters are handled properly. +func TestJobControl(t *testing.T) { + if err := testutil.Pull("alpine"); err != nil { + t.Fatalf("docker pull failed: %v", err) + } + d := testutil.MakeDocker("job-control-test") + + // Start the container with an attached PTY. + _, ptmx, err := d.RunWithPty("alpine", "sh") + if err != nil { + t.Fatalf("docker run failed: %v", err) + } + defer ptmx.Close() + defer d.CleanUp() + + // Call "sleep 100" in the shell. + if _, err := ptmx.Write([]byte("sleep 100\n")); err != nil { + t.Fatalf("error writing to pty: %v", err) + } + + // Give shell a few seconds to start executing the sleep. + time.Sleep(2 * time.Second) + + // Send a ^C to the pty, which should kill sleep, but not the shell. + // \x03 is ASCII "end of text", which is the same as ^C. + if _, err := ptmx.Write([]byte{'\x03'}); err != nil { + t.Fatalf("error writing to pty: %v", err) + } + + // The shell should still be alive at this point. Sleep should have + // exited with code 2+128=130. We'll exit with 10 plus that number, so + // that we can be sure that the shell did not get signalled. + if _, err := ptmx.Write([]byte("exit $(expr $? + 10)\n")); err != nil { + t.Fatalf("error writing to pty: %v", err) + } + + // Wait for the container to exit. + got, err := d.Wait(5 * time.Second) + if err != nil { + t.Fatalf("error getting exit code: %v", err) + } + // Container should exit with code 10+130=140. + if want := syscall.WaitStatus(140); got != want { + t.Errorf("container exited with code %d want %d", got, want) + } +} + func TestMain(m *testing.M) { testutil.EnsureSupportedDockerVersion() os.Exit(m.Run()) |