mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge remote-tracking branch 'robryk/cmdstream-deadlock'
This commit is contained in:
commit
fdae64d8d7
2 changed files with 23 additions and 5 deletions
14
archive.go
14
archive.go
|
@ -55,17 +55,21 @@ func CmdStream(cmd *exec.Cmd) (io.Reader, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pipeR, pipeW := io.Pipe()
|
pipeR, pipeW := io.Pipe()
|
||||||
|
errChan := make(chan []byte)
|
||||||
|
go func() {
|
||||||
|
errText, e := ioutil.ReadAll(stderr)
|
||||||
|
if e != nil {
|
||||||
|
errText = []byte("(...couldn't fetch stderr: " + e.Error() + ")")
|
||||||
|
}
|
||||||
|
errChan <- errText
|
||||||
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
_, err := io.Copy(pipeW, stdout)
|
_, err := io.Copy(pipeW, stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pipeW.CloseWithError(err)
|
pipeW.CloseWithError(err)
|
||||||
}
|
}
|
||||||
errText, e := ioutil.ReadAll(stderr)
|
errText := <-errChan
|
||||||
if e != nil {
|
|
||||||
errText = []byte("(...couldn't fetch stderr: " + e.Error() + ")")
|
|
||||||
}
|
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
// FIXME: can this block if stderr outputs more than the size of StderrPipe()'s buffer?
|
|
||||||
pipeW.CloseWithError(errors.New(err.Error() + ": " + string(errText)))
|
pipeW.CloseWithError(errors.New(err.Error() + ": " + string(errText)))
|
||||||
} else {
|
} else {
|
||||||
pipeW.Close()
|
pipeW.Close()
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestCmdStreamLargeStderr(t *testing.T) {
|
||||||
|
// This test checks for deadlock; thus, the main failure mode of this test is deadlocking.
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
|
||||||
|
out, err := CmdStream(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start command: " + err.Error())
|
||||||
|
}
|
||||||
|
_, err = io.Copy(ioutil.Discard, out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Command should not have failed (err=%s...)", err.Error()[:100])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCmdStreamBad(t *testing.T) {
|
func TestCmdStreamBad(t *testing.T) {
|
||||||
badCmd := exec.Command("/bin/sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
|
badCmd := exec.Command("/bin/sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
|
||||||
out, err := CmdStream(badCmd)
|
out, err := CmdStream(badCmd)
|
||||||
|
|
Loading…
Reference in a new issue