1
0
mirror of https://github.com/moby/moby.git synced 2025-08-01 05:47:11 +03:00

Merge pull request #40595 from sfzhu93/GL_2_25

[integration] add buffer to prevent goroutine leak
This commit is contained in:
Sebastiaan van Stijn
2020-05-08 16:00:52 +02:00
committed by GitHub
22 changed files with 63 additions and 45 deletions

View File

@ -43,14 +43,14 @@ func (s *DockerSuite) TestGetContainersAttachWebsocket(c *testing.T) {
expected := []byte("hello") expected := []byte("hello")
actual := make([]byte, len(expected)) actual := make([]byte, len(expected))
outChan := make(chan error) outChan := make(chan error, 1)
go func() { go func() {
_, err := io.ReadFull(ws, actual) _, err := io.ReadFull(ws, actual)
outChan <- err outChan <- err
close(outChan) close(outChan)
}() }()
inChan := make(chan error) inChan := make(chan error, 1)
go func() { go func() {
_, err := ws.Write(expected) _, err := ws.Write(expected)
inChan <- err inChan <- err
@ -279,7 +279,7 @@ func bodyIsWritable(r *http.Response) bool {
// readTimeout read from io.Reader with timeout // readTimeout read from io.Reader with timeout
func readTimeout(r io.Reader, buf []byte, timeout time.Duration) (n int, err error) { func readTimeout(r io.Reader, buf []byte, timeout time.Duration) (n int, err error) {
ch := make(chan bool) ch := make(chan bool, 1)
go func() { go func() {
n, err = io.ReadFull(r, buf) n, err = io.ReadFull(r, buf)
ch <- true ch <- true

View File

@ -338,7 +338,7 @@ func (s *DockerSuite) TestGetStoppedContainerStats(c *testing.T) {
name := "statscontainer" name := "statscontainer"
dockerCmd(c, "create", "--name", name, "busybox", "ps") dockerCmd(c, "create", "--name", name, "busybox", "ps")
chResp := make(chan error) chResp := make(chan error, 1)
// We expect an immediate response, but if it's not immediate, the test would hang, so put it in a goroutine // We expect an immediate response, but if it's not immediate, the test would hang, so put it in a goroutine
// below we'll check this on a timeout. // below we'll check this on a timeout.

View File

@ -30,7 +30,7 @@ func (s *DockerSuite) TestLogsAPIWithStdout(c *testing.T) {
err error err error
} }
chLog := make(chan logOut) chLog := make(chan logOut, 1)
res, body, err := request.Get(fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&timestamps=1", id)) res, body, err := request.Get(fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&timestamps=1", id))
assert.NilError(c, err) assert.NilError(c, err)
assert.Equal(c, res.StatusCode, http.StatusOK) assert.Equal(c, res.StatusCode, http.StatusOK)
@ -116,6 +116,8 @@ func (s *DockerSuite) TestLogsAPIUntilFutureFollow(c *testing.T) {
} }
chLog := make(chan logOut) chLog := make(chan logOut)
stop := make(chan struct{})
defer close(stop)
go func() { go func() {
bufReader := bufio.NewReader(reader) bufReader := bufio.NewReader(reader)
@ -126,11 +128,20 @@ func (s *DockerSuite) TestLogsAPIUntilFutureFollow(c *testing.T) {
if err == io.EOF { if err == io.EOF {
return return
} }
chLog <- logOut{"", err} select {
case <-stop:
return
case chLog <- logOut{"", err}:
}
return return
} }
chLog <- logOut{strings.TrimSpace(string(out)), err} select {
case <-stop:
return
case chLog <- logOut{strings.TrimSpace(string(out)), err}:
}
} }
}() }()

View File

@ -102,7 +102,7 @@ func (s *DockerSuite) TestAttachTTYWithoutStdin(c *testing.T) {
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
assert.NilError(c, waitRun(id)) assert.NilError(c, waitRun(id))
done := make(chan error) done := make(chan error, 1)
go func() { go func() {
defer close(done) defer close(done)

View File

@ -33,7 +33,7 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *testing.T) {
err = attachCmd.Start() err = attachCmd.Start()
assert.NilError(c, err) assert.NilError(c, err)
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
time.Sleep(300 * time.Millisecond) time.Sleep(300 * time.Millisecond)
defer close(errChan) defer close(errChan)
@ -68,7 +68,7 @@ func (s *DockerSuite) TestAttachAfterDetach(c *testing.T) {
cmd.Stdout = tty cmd.Stdout = tty
cmd.Stderr = tty cmd.Stderr = tty
cmdExit := make(chan error) cmdExit := make(chan error, 1)
go func() { go func() {
cmdExit <- cmd.Run() cmdExit <- cmd.Run()
close(cmdExit) close(cmdExit)

View File

@ -490,7 +490,7 @@ func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *testing.T) {
})) }))
defer ctx.Close() defer ctx.Close()
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
errChan <- buildImage(name, build.WithExternalBuildContext(ctx)).Error errChan <- buildImage(name, build.WithExternalBuildContext(ctx)).Error
close(errChan) close(errChan)
@ -833,7 +833,7 @@ COPY test_file .`),
})) }))
defer ctx.Close() defer ctx.Close()
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
errChan <- buildImage(name, build.WithExternalBuildContext(ctx)).Error errChan <- buildImage(name, build.WithExternalBuildContext(ctx)).Error
close(errChan) close(errChan)

View File

@ -1246,7 +1246,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *testing.T) {
s.d.Restart(c) s.d.Restart(c)
errchan := make(chan error) errchan := make(chan error, 1)
go func() { go func() {
if out, err := s.d.Cmd("wait", containerID); err != nil { if out, err := s.d.Cmd("wait", containerID); err != nil {
errchan <- fmt.Errorf("%v:\n%s", err, out) errchan <- fmt.Errorf("%v:\n%s", err, out)
@ -1599,15 +1599,17 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *testing.T) {
} }
s.d.Restart(c) s.d.Restart(c)
errchan := make(chan error) errchan := make(chan error, 1)
go func() { go func() {
out, err := s.d.Cmd("start", "test") out, err := s.d.Cmd("start", "test")
if err != nil { if err != nil {
errchan <- fmt.Errorf("%v:\n%s", err, out) errchan <- fmt.Errorf("%v:\n%s", err, out)
return
} }
name := strings.TrimSpace(out) name := strings.TrimSpace(out)
if name != "test" { if name != "test" {
errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name) errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name)
return
} }
close(errchan) close(errchan)
}() }()

View File

@ -51,7 +51,7 @@ func (s *DockerSuite) TestEventsRedirectStdout(c *testing.T) {
func (s *DockerSuite) TestEventsOOMDisableFalse(c *testing.T) { func (s *DockerSuite) TestEventsOOMDisableFalse(c *testing.T) {
testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, swapMemorySupport, NotPpc64le) testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, swapMemorySupport, NotPpc64le)
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
defer close(errChan) defer close(errChan)
out, exitCode, _ := dockerCmdWithError("run", "--name", "oomFalse", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") out, exitCode, _ := dockerCmdWithError("run", "--name", "oomFalse", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
@ -81,7 +81,7 @@ func (s *DockerSuite) TestEventsOOMDisableFalse(c *testing.T) {
func (s *DockerSuite) TestEventsOOMDisableTrue(c *testing.T) { func (s *DockerSuite) TestEventsOOMDisableTrue(c *testing.T) {
testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotArm, swapMemorySupport, NotPpc64le) testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotArm, swapMemorySupport, NotPpc64le)
errChan := make(chan error) errChan := make(chan error, 1)
observer, err := newEventObserver(c) observer, err := newEventObserver(c)
assert.NilError(c, err) assert.NilError(c, err)
err = observer.Start() err = observer.Start()

View File

@ -53,7 +53,7 @@ func (s *DockerSuite) TestExecInteractive(c *testing.T) {
assert.Equal(c, line, "test") assert.Equal(c, line, "test")
err = stdin.Close() err = stdin.Close()
assert.NilError(c, err) assert.NilError(c, err)
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
errChan <- execCmd.Wait() errChan <- execCmd.Wait()
close(errChan) close(errChan)
@ -170,7 +170,7 @@ func (s *DockerSuite) TestExecTTYWithoutStdin(c *testing.T) {
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
assert.NilError(c, waitRun(id)) assert.NilError(c, waitRun(id))
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
defer close(errChan) defer close(errChan)
@ -230,7 +230,7 @@ func (s *DockerSuite) TestExecStopNotHanging(c *testing.T) {
out string out string
err error err error
} }
ch := make(chan dstop) ch := make(chan dstop, 1)
go func() { go func() {
result := icmd.RunCommand(dockerBinary, "stop", "testing") result := icmd.RunCommand(dockerBinary, "stop", "testing")
ch <- dstop{result.Combined(), result.Error} ch <- dstop{result.Combined(), result.Error}
@ -256,11 +256,12 @@ func (s *DockerSuite) TestExecCgroup(c *testing.T) {
var wg sync.WaitGroup var wg sync.WaitGroup
var mu sync.Mutex var mu sync.Mutex
var execCgroups []sort.StringSlice var execCgroups []sort.StringSlice
errChan := make(chan error) errChan := make(chan error, 5)
// exec a few times concurrently to get consistent failure // exec a few times concurrently to get consistent failure
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done()
out, _, err := dockerCmdWithError("exec", "testing", "cat", "/proc/self/cgroup") out, _, err := dockerCmdWithError("exec", "testing", "cat", "/proc/self/cgroup")
if err != nil { if err != nil {
errChan <- err errChan <- err
@ -271,7 +272,6 @@ func (s *DockerSuite) TestExecCgroup(c *testing.T) {
mu.Lock() mu.Lock()
execCgroups = append(execCgroups, cg) execCgroups = append(execCgroups, cg)
mu.Unlock() mu.Unlock()
wg.Done()
}() }()
} }
wg.Wait() wg.Wait()

View File

@ -26,7 +26,7 @@ func (s *DockerSuite) TestExecInteractiveStdinClose(c *testing.T) {
b := bytes.NewBuffer(nil) b := bytes.NewBuffer(nil)
ch := make(chan error) ch := make(chan error, 1)
go func() { ch <- cmd.Wait() }() go func() { ch <- cmd.Wait() }()
select { select {
@ -56,7 +56,7 @@ func (s *DockerSuite) TestExecTTY(c *testing.T) {
_, err = p.Write([]byte("cat /foo && exit\n")) _, err = p.Write([]byte("cat /foo && exit\n"))
assert.NilError(c, err) assert.NilError(c, err)
chErr := make(chan error) chErr := make(chan error, 1)
go func() { go func() {
chErr <- cmd.Wait() chErr <- cmd.Wait()
}() }()

View File

@ -365,7 +365,7 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverLookupNotBlocked(c *
defer os.RemoveAll(specPath) defer os.RemoveAll(specPath)
chCmd1 := make(chan struct{}) chCmd1 := make(chan struct{})
chCmd2 := make(chan error) chCmd2 := make(chan error, 1)
cmd1 := exec.Command(dockerBinary, "volume", "create", "-d", "down-driver") cmd1 := exec.Command(dockerBinary, "volume", "create", "-d", "down-driver")
cmd2 := exec.Command(dockerBinary, "volume", "create") cmd2 := exec.Command(dockerBinary, "volume", "create")
@ -398,7 +398,7 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverRetryNotImmediatelyE
s.d.StartWithBusybox(c) s.d.StartWithBusybox(c)
driverName := "test-external-volume-driver-retry" driverName := "test-external-volume-driver-retry"
errchan := make(chan error) errchan := make(chan error, 1)
started := make(chan struct{}) started := make(chan struct{})
go func() { go func() {
close(started) close(started)

View File

@ -128,7 +128,7 @@ func (s *DockerSuite) TestLogsFollowStopped(c *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "-f", id) logsCmd := exec.Command(dockerBinary, "logs", "-f", id)
assert.NilError(c, logsCmd.Start()) assert.NilError(c, logsCmd.Start())
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
errChan <- logsCmd.Wait() errChan <- logsCmd.Wait()
close(errChan) close(errChan)

View File

@ -82,8 +82,8 @@ func testConcurrentPullWholeRepo(c *testing.T) {
dockerCmd(c, args...) dockerCmd(c, args...)
// Run multiple re-pulls concurrently // Run multiple re-pulls concurrently
results := make(chan error)
numPulls := 3 numPulls := 3
results := make(chan error, numPulls)
for i := 0; i != numPulls; i++ { for i := 0; i != numPulls; i++ {
go func() { go func() {
@ -120,8 +120,8 @@ func testConcurrentFailingPull(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
// Run multiple pulls concurrently // Run multiple pulls concurrently
results := make(chan error)
numPulls := 3 numPulls := 3
results := make(chan error, numPulls)
for i := 0; i != numPulls; i++ { for i := 0; i != numPulls; i++ {
go func() { go func() {
@ -170,7 +170,7 @@ func testConcurrentPullMultipleTags(c *testing.T) {
dockerCmd(c, args...) dockerCmd(c, args...)
// Re-pull individual tags, in parallel // Re-pull individual tags, in parallel
results := make(chan error) results := make(chan error, len(repos))
for _, repo := range repos { for _, repo := range repos {
go func(repo string) { go func(repo string) {

View File

@ -162,7 +162,7 @@ func testConcurrentPush(c *testing.T) {
} }
// Push tags, in parallel // Push tags, in parallel
results := make(chan error) results := make(chan error, len(repos))
for _, repo := range repos { for _, repo := range repos {
go func(repo string) { go func(repo string) {

View File

@ -1765,7 +1765,7 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *testing.T) {
if err := stdin.Close(); err != nil { if err := stdin.Close(); err != nil {
c.Fatal(err) c.Fatal(err)
} }
finish := make(chan error) finish := make(chan error, 1)
go func() { go func() {
finish <- runCmd.Wait() finish <- runCmd.Wait()
close(finish) close(finish)
@ -2523,7 +2523,7 @@ func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *testing.T) {
} }
func (s *DockerSuite) TestRunTTYWithPipe(c *testing.T) { func (s *DockerSuite) TestRunTTYWithPipe(c *testing.T) {
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
defer close(errChan) defer close(errChan)
@ -2810,7 +2810,7 @@ func (s *DockerSuite) TestRunPIDHostWithChildIsKillable(c *testing.T) {
assert.Assert(c, waitRun(name) == nil) assert.Assert(c, waitRun(name) == nil)
errchan := make(chan error) errchan := make(chan error, 1)
go func() { go func() {
if out, _, err := dockerCmdWithError("kill", name); err != nil { if out, _, err := dockerCmdWithError("kill", name); err != nil {
errchan <- fmt.Errorf("%v:\n%s", err, out) errchan <- fmt.Errorf("%v:\n%s", err, out)
@ -3622,7 +3622,7 @@ func (s *DockerSuite) TestRunStdinBlockedAfterContainerExit(c *testing.T) {
cmd.Stderr = stdout cmd.Stderr = stdout
assert.Assert(c, cmd.Start() == nil) assert.Assert(c, cmd.Start() == nil)
waitChan := make(chan error) waitChan := make(chan error, 1)
go func() { go func() {
waitChan <- cmd.Wait() waitChan <- cmd.Wait()
}() }()

View File

@ -40,7 +40,7 @@ func (s *DockerSuite) TestRunRedirectStdout(c *testing.T) {
cmd.Stdout = tty cmd.Stdout = tty
cmd.Stderr = tty cmd.Stderr = tty
assert.NilError(c, cmd.Start()) assert.NilError(c, cmd.Start())
ch := make(chan error) ch := make(chan error, 1)
go func() { go func() {
ch <- cmd.Wait() ch <- cmd.Wait()
close(ch) close(ch)
@ -122,7 +122,7 @@ func (s *DockerSuite) TestRunAttachDetach(c *testing.T) {
_, err = cpty.Write([]byte{17}) _, err = cpty.Write([]byte{17})
assert.NilError(c, err) assert.NilError(c, err)
ch := make(chan struct{}) ch := make(chan struct{}, 1)
go func() { go func() {
cmd.Wait() cmd.Wait()
ch <- struct{}{} ch <- struct{}{}
@ -188,7 +188,7 @@ func (s *DockerSuite) TestRunAttachDetachFromFlag(c *testing.T) {
c.Fatal(err) c.Fatal(err)
} }
ch := make(chan struct{}) ch := make(chan struct{}, 1)
go func() { go func() {
cmd.Wait() cmd.Wait()
ch <- struct{}{} ch <- struct{}{}
@ -304,7 +304,7 @@ func (s *DockerSuite) TestRunAttachDetachFromConfig(c *testing.T) {
c.Fatal(err) c.Fatal(err)
} }
ch := make(chan struct{}) ch := make(chan struct{}, 1)
go func() { go func() {
cmd.Wait() cmd.Wait()
ch <- struct{}{} ch <- struct{}{}
@ -387,7 +387,7 @@ func (s *DockerSuite) TestRunAttachDetachKeysOverrideConfig(c *testing.T) {
c.Fatal(err) c.Fatal(err)
} }
ch := make(chan struct{}) ch := make(chan struct{}, 1)
go func() { go func() {
cmd.Wait() cmd.Wait()
ch <- struct{}{} ch <- struct{}{}
@ -615,7 +615,7 @@ func (s *DockerSuite) TestRunWithInvalidPathforBlkioDeviceWriteIOps(c *testing.T
func (s *DockerSuite) TestRunOOMExitCode(c *testing.T) { func (s *DockerSuite) TestRunOOMExitCode(c *testing.T) {
testRequires(c, memoryLimitSupport, swapMemorySupport, NotPpc64le) testRequires(c, memoryLimitSupport, swapMemorySupport, NotPpc64le)
errChan := make(chan error) errChan := make(chan error, 1)
go func() { go func() {
defer close(errChan) defer close(errChan)
// memory limit lower than 8MB will raise an error of "device or resource busy" from docker-runc. // memory limit lower than 8MB will raise an error of "device or resource busy" from docker-runc.

View File

@ -177,6 +177,8 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) {
// Make sure pipe is written to // Make sure pipe is written to
ch := make(chan *logMessage) ch := make(chan *logMessage)
done := make(chan struct{}) done := make(chan struct{})
stop := make(chan struct{})
defer close(stop)
go func() { go func() {
reader := bufio.NewReader(r) reader := bufio.NewReader(r)
for { for {
@ -184,6 +186,8 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) {
msg.data, _, msg.err = reader.ReadLine() msg.data, _, msg.err = reader.ReadLine()
select { select {
case ch <- msg: case ch <- msg:
case <-stop:
return
case <-done: case <-done:
return return
} }

View File

@ -26,7 +26,7 @@ func (s *DockerSuite) TestStartAttachReturnsOnError(c *testing.T) {
// err shouldn't be nil because container test2 try to link to stopped container // err shouldn't be nil because container test2 try to link to stopped container
assert.Assert(c, err != nil, "out: %s", out) assert.Assert(c, err != nil, "out: %s", out)
ch := make(chan error) ch := make(chan error, 1)
go func() { go func() {
// Attempt to start attached to the container that won't start // Attempt to start attached to the container that won't start
// This should return an error immediately since the container can't be started // This should return an error immediately since the container can't be started

View File

@ -26,7 +26,7 @@ func (s *DockerSuite) TestStatsNoStream(c *testing.T) {
err error err error
} }
ch := make(chan output) ch := make(chan output, 1)
go func() { go func() {
out, err := statsCmd.Output() out, err := statsCmd.Output()
ch <- output{out, err} ch <- output{out, err}

View File

@ -53,7 +53,7 @@ func TestExecWithCloseStdin(t *testing.T) {
resCh = make(chan struct { resCh = make(chan struct {
content string content string
err error err error
}) }, 1)
) )
go func() { go func() {

View File

@ -47,7 +47,7 @@ func TestContinueAfterPluginCrash(t *testing.T) {
attach, err := client.ContainerAttach(context.Background(), id, types.ContainerAttachOptions{Stream: true, Stdout: true}) attach, err := client.ContainerAttach(context.Background(), id, types.ContainerAttachOptions{Stream: true, Stdout: true})
assert.NilError(t, err) assert.NilError(t, err)
chErr := make(chan error) chErr := make(chan error, 1)
go func() { go func() {
defer close(chErr) defer close(chErr)
rdr := bufio.NewReader(attach.Reader) rdr := bufio.NewReader(attach.Reader)

View File

@ -645,13 +645,14 @@ func (d *Daemon) ReloadConfig() error {
return errors.New("daemon is not running") return errors.New("daemon is not running")
} }
errCh := make(chan error) errCh := make(chan error, 1)
started := make(chan struct{}) started := make(chan struct{})
go func() { go func() {
_, body, err := request.Get("/events", request.Host(d.Sock())) _, body, err := request.Get("/events", request.Host(d.Sock()))
close(started) close(started)
if err != nil { if err != nil {
errCh <- err errCh <- err
return
} }
defer body.Close() defer body.Close()
dec := json.NewDecoder(body) dec := json.NewDecoder(body)