diff --git a/api_test.go b/api_test.go index 13731dbf9e..a0724b0ba3 100644 --- a/api_test.go +++ b/api_test.go @@ -895,6 +895,12 @@ func TestPostContainersAttach(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() + // Try to avoid the timeoout in destroy. Best effort, don't check error + defer func() { + closeWrap(stdin, stdinPipe, stdout, stdoutPipe) + container.Kill() + }() + // Attach to it c1 := make(chan struct{}) go func() { @@ -934,7 +940,7 @@ func TestPostContainersAttach(t *testing.T) { } // Wait for attach to finish, the client disconnected, therefore, Attach finished his job - setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() { + setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() { <-c1 }) diff --git a/container.go b/container.go index dea81b6def..ec4abffc1b 100644 --- a/container.go +++ b/container.go @@ -379,14 +379,15 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s utils.Debugf("[start] attach stdin\n") defer utils.Debugf("[end] attach stdin\n") // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr - if cStdout != nil { - defer cStdout.Close() - } - if cStderr != nil { - defer cStderr.Close() - } if container.Config.StdinOnce && !container.Config.Tty { defer cStdin.Close() + } else { + if cStdout != nil { + defer cStdout.Close() + } + if cStderr != nil { + defer cStderr.Close() + } } if container.Config.Tty { _, err = utils.CopyEscapable(cStdin, stdin) diff --git a/runtime_test.go b/runtime_test.go index 807097404d..0b0f62f199 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -8,6 +8,7 @@ import ( "log" "net" "os" + "runtime" "strconv" "strings" "sync" @@ -25,7 +26,11 @@ const ( testDaemonProto = "tcp" ) -var globalRuntime *Runtime +var ( + globalRuntime *Runtime + startFds int + startGoroutines int +) func nuke(runtime *Runtime) error { var wg sync.WaitGroup @@ -80,21 +85,21 @@ func init() { NetworkBridgeIface = unitTestNetworkBridge // Make it our Store root - runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false) - if err != nil { + if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false); err != nil { panic(err) + } else { + globalRuntime = runtime } - globalRuntime = runtime // Create the "Server" srv := &Server{ - runtime: runtime, + runtime: globalRuntime, enableCors: false, pullingPool: make(map[string]struct{}), pushingPool: make(map[string]struct{}), } // If the unit test is not found, try to download it. - if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID { + if img, err := globalRuntime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID { // Retrieve the Image if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil { panic(err) @@ -109,6 +114,8 @@ func init() { // Give some time to ListenAndServer to actually start time.Sleep(time.Second) + + startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine() } // FIXME: test that ImagePull(json=true) send correct json output diff --git a/z_final_test.go b/z_final_test.go index 78a7acf6e7..08a180baaf 100644 --- a/z_final_test.go +++ b/z_final_test.go @@ -6,7 +6,12 @@ import ( "testing" ) -func TestFinal(t *testing.T) { - cleanup(globalRuntime) +func displayFdGoroutines(t *testing.T) { t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine()) } + +func TestFinal(t *testing.T) { + cleanup(globalRuntime) + t.Logf("Start Fds: %d, Start Goroutines: %d", startFds, startGoroutines) + displayFdGoroutines(t) +}