Signed-off-by: Darren Stahl <darst@microsoft.com>
| ... | ... |
@@ -82,10 +82,10 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
| 82 | 82 |
} |
| 83 | 83 |
return daemon.postRunProcessing(c, e) |
| 84 | 84 |
case libcontainerd.StateExitProcess: |
| 85 |
- c.Lock() |
|
| 86 |
- defer c.Unlock() |
|
| 87 | 85 |
if execConfig := c.ExecCommands.Get(e.ProcessID); execConfig != nil {
|
| 88 | 86 |
ec := int(e.ExitCode) |
| 87 |
+ execConfig.Lock() |
|
| 88 |
+ defer execConfig.Unlock() |
|
| 89 | 89 |
execConfig.ExitCode = &ec |
| 90 | 90 |
execConfig.Running = false |
| 91 | 91 |
execConfig.Wait() |
| ... | ... |
@@ -539,3 +539,63 @@ func (s *DockerSuite) TestExecEnvLinksHost(c *check.C) {
|
| 539 | 539 |
c.Assert(out, checker.Contains, "HOSTNAME=myhost") |
| 540 | 540 |
c.Assert(out, checker.Contains, "DB_NAME=/bar/db") |
| 541 | 541 |
} |
| 542 |
+ |
|
| 543 |
+func (s *DockerSuite) TestExecWindowsOpenHandles(c *check.C) {
|
|
| 544 |
+ testRequires(c, DaemonIsWindows) |
|
| 545 |
+ runSleepingContainer(c, "-d", "--name", "test") |
|
| 546 |
+ exec := make(chan bool) |
|
| 547 |
+ go func() {
|
|
| 548 |
+ dockerCmd(c, "exec", "test", "cmd", "/c", "start sleep 10") |
|
| 549 |
+ exec <- true |
|
| 550 |
+ }() |
|
| 551 |
+ |
|
| 552 |
+ for {
|
|
| 553 |
+ top := make(chan string) |
|
| 554 |
+ var out string |
|
| 555 |
+ go func() {
|
|
| 556 |
+ out, _ := dockerCmd(c, "top", "test") |
|
| 557 |
+ top <- out |
|
| 558 |
+ }() |
|
| 559 |
+ |
|
| 560 |
+ select {
|
|
| 561 |
+ case <-time.After(time.Second * 5): |
|
| 562 |
+ c.Error("timed out waiting for top while exec is exiting")
|
|
| 563 |
+ case out = <-top: |
|
| 564 |
+ break |
|
| 565 |
+ } |
|
| 566 |
+ |
|
| 567 |
+ if strings.Count(out, "busybox.exe") == 2 && !strings.Contains(out, "cmd.exe") {
|
|
| 568 |
+ // The initial exec process (cmd.exe) has exited, and both sleeps are currently running |
|
| 569 |
+ break |
|
| 570 |
+ } |
|
| 571 |
+ time.Sleep(1 * time.Second) |
|
| 572 |
+ } |
|
| 573 |
+ |
|
| 574 |
+ inspect := make(chan bool) |
|
| 575 |
+ go func() {
|
|
| 576 |
+ dockerCmd(c, "inspect", "test") |
|
| 577 |
+ inspect <- true |
|
| 578 |
+ }() |
|
| 579 |
+ |
|
| 580 |
+ select {
|
|
| 581 |
+ case <-time.After(time.Second * 5): |
|
| 582 |
+ c.Error("timed out waiting for inspect while exec is exiting")
|
|
| 583 |
+ case <-inspect: |
|
| 584 |
+ break |
|
| 585 |
+ } |
|
| 586 |
+ |
|
| 587 |
+ // Ensure the background sleep is still running |
|
| 588 |
+ out, _ := dockerCmd(c, "top", "test") |
|
| 589 |
+ c.Assert(strings.Count(out, "busybox.exe"), checker.Equals, 2) |
|
| 590 |
+ |
|
| 591 |
+ // The exec should exit when the background sleep exits |
|
| 592 |
+ select {
|
|
| 593 |
+ case <-time.After(time.Second * 15): |
|
| 594 |
+ c.Error("timed out waiting for async exec to exit")
|
|
| 595 |
+ case <-exec: |
|
| 596 |
+ // Ensure the background sleep has actually exited |
|
| 597 |
+ out, _ := dockerCmd(c, "top", "test") |
|
| 598 |
+ c.Assert(strings.Count(out, "busybox.exe"), checker.Equals, 1) |
|
| 599 |
+ break |
|
| 600 |
+ } |
|
| 601 |
+} |