Browse code

Fixes #505 - Make sure all output is send on the network before closing

Guillaume J. Charmes authored on 2013/07/25 07:48:18
Showing 4 changed files
... ...
@@ -895,6 +895,12 @@ func TestPostContainersAttach(t *testing.T) {
895 895
 	stdin, stdinPipe := io.Pipe()
896 896
 	stdout, stdoutPipe := io.Pipe()
897 897
 
898
+	// Try to avoid the timeoout in destroy. Best effort, don't check error
899
+	defer func() {
900
+		closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
901
+		container.Kill()
902
+	}()
903
+
898 904
 	// Attach to it
899 905
 	c1 := make(chan struct{})
900 906
 	go func() {
... ...
@@ -934,7 +940,7 @@ func TestPostContainersAttach(t *testing.T) {
934 934
 	}
935 935
 
936 936
 	// Wait for attach to finish, the client disconnected, therefore, Attach finished his job
937
-	setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
937
+	setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
938 938
 		<-c1
939 939
 	})
940 940
 
... ...
@@ -379,14 +379,15 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
379 379
 				utils.Debugf("[start] attach stdin\n")
380 380
 				defer utils.Debugf("[end] attach stdin\n")
381 381
 				// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
382
-				if cStdout != nil {
383
-					defer cStdout.Close()
384
-				}
385
-				if cStderr != nil {
386
-					defer cStderr.Close()
387
-				}
388 382
 				if container.Config.StdinOnce && !container.Config.Tty {
389 383
 					defer cStdin.Close()
384
+				} else {
385
+					if cStdout != nil {
386
+						defer cStdout.Close()
387
+					}
388
+					if cStderr != nil {
389
+						defer cStderr.Close()
390
+					}
390 391
 				}
391 392
 				if container.Config.Tty {
392 393
 					_, err = utils.CopyEscapable(cStdin, stdin)
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"log"
9 9
 	"net"
10 10
 	"os"
11
+	"runtime"
11 12
 	"strconv"
12 13
 	"strings"
13 14
 	"sync"
... ...
@@ -25,7 +26,11 @@ const (
25 25
 	testDaemonProto       = "tcp"
26 26
 )
27 27
 
28
-var globalRuntime *Runtime
28
+var (
29
+	globalRuntime   *Runtime
30
+	startFds        int
31
+	startGoroutines int
32
+)
29 33
 
30 34
 func nuke(runtime *Runtime) error {
31 35
 	var wg sync.WaitGroup
... ...
@@ -80,21 +85,21 @@ func init() {
80 80
 	NetworkBridgeIface = unitTestNetworkBridge
81 81
 
82 82
 	// Make it our Store root
83
-	runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false)
84
-	if err != nil {
83
+	if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false); err != nil {
85 84
 		panic(err)
85
+	} else {
86
+		globalRuntime = runtime
86 87
 	}
87
-	globalRuntime = runtime
88 88
 
89 89
 	// Create the "Server"
90 90
 	srv := &Server{
91
-		runtime:     runtime,
91
+		runtime:     globalRuntime,
92 92
 		enableCors:  false,
93 93
 		pullingPool: make(map[string]struct{}),
94 94
 		pushingPool: make(map[string]struct{}),
95 95
 	}
96 96
 	// If the unit test is not found, try to download it.
97
-	if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
97
+	if img, err := globalRuntime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
98 98
 		// Retrieve the Image
99 99
 		if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil {
100 100
 			panic(err)
... ...
@@ -109,6 +114,8 @@ func init() {
109 109
 
110 110
 	// Give some time to ListenAndServer to actually start
111 111
 	time.Sleep(time.Second)
112
+
113
+	startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine()
112 114
 }
113 115
 
114 116
 // FIXME: test that ImagePull(json=true) send correct json output
... ...
@@ -6,7 +6,12 @@ import (
6 6
 	"testing"
7 7
 )
8 8
 
9
+func displayFdGoroutines(t *testing.T) {
10
+	t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine())
11
+}
12
+
9 13
 func TestFinal(t *testing.T) {
10 14
 	cleanup(globalRuntime)
11
-	t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine())
15
+	t.Logf("Start Fds: %d, Start Goroutines: %d", startFds, startGoroutines)
16
+	displayFdGoroutines(t)
12 17
 }