Fix escape-keys by preserving input if invalid
| ... | ... |
@@ -484,7 +484,9 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64 |
| 484 | 484 |
nr, er := src.Read(buf) |
| 485 | 485 |
if nr > 0 {
|
| 486 | 486 |
// ---- Docker addition |
| 487 |
+ preservBuf := []byte{}
|
|
| 487 | 488 |
for i, key := range keys {
|
| 489 |
+ preservBuf = append(preservBuf, buf[0:nr]...) |
|
| 488 | 490 |
if nr != 1 || buf[0] != key {
|
| 489 | 491 |
break |
| 490 | 492 |
} |
| ... | ... |
@@ -496,8 +498,15 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64 |
| 496 | 496 |
} |
| 497 | 497 |
nr, er = src.Read(buf) |
| 498 | 498 |
} |
| 499 |
- // ---- End of docker |
|
| 500 |
- nw, ew := dst.Write(buf[0:nr]) |
|
| 499 |
+ var nw int |
|
| 500 |
+ var ew error |
|
| 501 |
+ if len(preservBuf) > 0 {
|
|
| 502 |
+ nw, ew = dst.Write(preservBuf) |
|
| 503 |
+ nr = len(preservBuf) |
|
| 504 |
+ } else {
|
|
| 505 |
+ // ---- End of docker |
|
| 506 |
+ nw, ew = dst.Write(buf[0:nr]) |
|
| 507 |
+ } |
|
| 501 | 508 |
if nw > 0 {
|
| 502 | 509 |
written += int64(nw) |
| 503 | 510 |
} |
| ... | ... |
@@ -396,6 +396,55 @@ func (s *DockerSuite) TestRunAttachDetachKeysOverrideConfig(c *check.C) {
|
| 396 | 396 |
c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
|
| 397 | 397 |
} |
| 398 | 398 |
|
| 399 |
+func (s *DockerSuite) TestRunAttachInvalidDetachKeySequencePreserved(c *check.C) {
|
|
| 400 |
+ name := "attach-detach" |
|
| 401 |
+ keyA := []byte{97}
|
|
| 402 |
+ keyB := []byte{98}
|
|
| 403 |
+ |
|
| 404 |
+ dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") |
|
| 405 |
+ |
|
| 406 |
+ cmd := exec.Command(dockerBinary, "attach", "--detach-keys='a,b,c'", name) |
|
| 407 |
+ stdout, err := cmd.StdoutPipe() |
|
| 408 |
+ if err != nil {
|
|
| 409 |
+ c.Fatal(err) |
|
| 410 |
+ } |
|
| 411 |
+ cpty, tty, err := pty.Open() |
|
| 412 |
+ if err != nil {
|
|
| 413 |
+ c.Fatal(err) |
|
| 414 |
+ } |
|
| 415 |
+ defer cpty.Close() |
|
| 416 |
+ cmd.Stdin = tty |
|
| 417 |
+ if err := cmd.Start(); err != nil {
|
|
| 418 |
+ c.Fatal(err) |
|
| 419 |
+ } |
|
| 420 |
+ c.Assert(waitRun(name), check.IsNil) |
|
| 421 |
+ |
|
| 422 |
+ // Invalid escape sequence aba, should print aba in output |
|
| 423 |
+ if _, err := cpty.Write(keyA); err != nil {
|
|
| 424 |
+ c.Fatal(err) |
|
| 425 |
+ } |
|
| 426 |
+ time.Sleep(100 * time.Millisecond) |
|
| 427 |
+ if _, err := cpty.Write(keyB); err != nil {
|
|
| 428 |
+ c.Fatal(err) |
|
| 429 |
+ } |
|
| 430 |
+ time.Sleep(100 * time.Millisecond) |
|
| 431 |
+ if _, err := cpty.Write(keyA); err != nil {
|
|
| 432 |
+ c.Fatal(err) |
|
| 433 |
+ } |
|
| 434 |
+ time.Sleep(100 * time.Millisecond) |
|
| 435 |
+ if _, err := cpty.Write([]byte("\n")); err != nil {
|
|
| 436 |
+ c.Fatal(err) |
|
| 437 |
+ } |
|
| 438 |
+ |
|
| 439 |
+ out, err := bufio.NewReader(stdout).ReadString('\n')
|
|
| 440 |
+ if err != nil {
|
|
| 441 |
+ c.Fatal(err) |
|
| 442 |
+ } |
|
| 443 |
+ if strings.TrimSpace(out) != "aba" {
|
|
| 444 |
+ c.Fatalf("expected 'aba', got %q", out)
|
|
| 445 |
+ } |
|
| 446 |
+} |
|
| 447 |
+ |
|
| 399 | 448 |
// "test" should be printed |
| 400 | 449 |
func (s *DockerSuite) TestRunWithCPUQuota(c *check.C) {
|
| 401 | 450 |
testRequires(c, cpuCfsQuota) |