1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #1281 from dotcloud/505-output_after_pipe-fix

- Runtime: Fixes #505 - Make sure all output is send on the network before closing
This commit is contained in:
Guillaume J. Charmes 2013-07-25 13:01:31 -07:00
commit 594c818d85
4 changed files with 34 additions and 15 deletions

View file

@ -895,6 +895,12 @@ func TestPostContainersAttach(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := 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 // Attach to it
c1 := make(chan struct{}) c1 := make(chan struct{})
go func() { go func() {
@ -934,7 +940,7 @@ func TestPostContainersAttach(t *testing.T) {
} }
// Wait for attach to finish, the client disconnected, therefore, Attach finished his job // 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 <-c1
}) })

View file

@ -379,14 +379,15 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
utils.Debugf("[start] attach stdin\n") utils.Debugf("[start] attach stdin\n")
defer utils.Debugf("[end] attach stdin\n") defer utils.Debugf("[end] attach stdin\n")
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr // 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 { if container.Config.StdinOnce && !container.Config.Tty {
defer cStdin.Close() defer cStdin.Close()
} else {
if cStdout != nil {
defer cStdout.Close()
}
if cStderr != nil {
defer cStderr.Close()
}
} }
if container.Config.Tty { if container.Config.Tty {
_, err = utils.CopyEscapable(cStdin, stdin) _, err = utils.CopyEscapable(cStdin, stdin)

View file

@ -8,6 +8,7 @@ import (
"log" "log"
"net" "net"
"os" "os"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -25,7 +26,11 @@ const (
testDaemonProto = "tcp" testDaemonProto = "tcp"
) )
var globalRuntime *Runtime var (
globalRuntime *Runtime
startFds int
startGoroutines int
)
func nuke(runtime *Runtime) error { func nuke(runtime *Runtime) error {
var wg sync.WaitGroup var wg sync.WaitGroup
@ -80,21 +85,21 @@ func init() {
NetworkBridgeIface = unitTestNetworkBridge NetworkBridgeIface = unitTestNetworkBridge
// Make it our Store root // Make it our Store root
runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false) if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false); err != nil {
if err != nil {
panic(err) panic(err)
} else {
globalRuntime = runtime
} }
globalRuntime = runtime
// Create the "Server" // Create the "Server"
srv := &Server{ srv := &Server{
runtime: runtime, runtime: globalRuntime,
enableCors: false, enableCors: false,
pullingPool: make(map[string]struct{}), pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}), pushingPool: make(map[string]struct{}),
} }
// If the unit test is not found, try to download it. // 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 // Retrieve the Image
if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil { if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil {
panic(err) panic(err)
@ -109,6 +114,8 @@ func init() {
// Give some time to ListenAndServer to actually start // Give some time to ListenAndServer to actually start
time.Sleep(time.Second) time.Sleep(time.Second)
startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine()
} }
// FIXME: test that ImagePull(json=true) send correct json output // FIXME: test that ImagePull(json=true) send correct json output

View file

@ -6,7 +6,12 @@ import (
"testing" "testing"
) )
func TestFinal(t *testing.T) { func displayFdGoroutines(t *testing.T) {
cleanup(globalRuntime)
t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine()) 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)
}