Browse code

Stop holding container lock while waiting on streams

Signed-off-by: Darren Stahl <darst@microsoft.com>

Darren Stahl authored on 2016/10/13 08:56:52
Showing 2 changed files
... ...
@@ -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
+}