-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Closed
Labels
Description
What version of Go are you using (go version
)?
- 1.6.2
- 1.6.3
- 1.7
What operating system and processor architecture are you using (go env
)?
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/usr/src/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build726085245=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
What did you do?
Let's use exec.Command to catch both stdout and stderr.
One of the pipes gets around 82855 chars ( magic number is between 65536 - 131072 ). Now ioutil.ReadAll will hang if I try to read from the second pipe before the first one ( full one ).
Here is the simplified example that only cat a file.
Original code was checking error and there is none of them there:
package main
import (
"fmt"
"io/ioutil"
"os/exec"
)
func main() {
cmd := exec.Command("cat", "file")
stdout, _ := cmd.StdoutPipe()
stderr, _ := cmd.StderrPipe()
cmd.Start()
be, _ := ioutil.ReadAll(stderr)
bo, _ := ioutil.ReadAll(stdout)
cmd.Wait()
fmt.Printf("%d be size \n", len(be))
fmt.Printf("%d bo size \n", len(bo))
}
If order of ReadAll would be opposite, this example will run correctly.
What did you expect to see?
Error or information in docs that those pipes should be handled differently.
What did you see instead?
Binary never exits.
Strace :
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] futex(0xc420056110, FUTEX_WAKE, 1 <unfinished ...>
[pid 18750] <... futex resumed> ) = 0
[pid 18746] <... futex resumed> ) = 1
[pid 18750] futex(0xc420056110, FUTEX_WAIT, 0, NULL <unfinished ...>
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] futex(0x53fc98, FUTEX_WAIT, 0, {60, 0}
) = -1 ETIMEDOUT (Connection timed out)
[pid 18746] select(0, NULL, NULL, NULL, {0, 20}) = 0 (Timeout)
[pid 18746] futex(0x53fc98, FUTEX_WAIT, 0, {60, 0}
Stack:
goroutine 1 [syscall, locked to thread]:
syscall.Syscall(0x0, 0x6, 0xc829b06000, 0x200, 0x0, 0xc82685daa0, 0x60)
/usr/local/go/src/syscall/asm_linux_amd64.s:18 +0x5
syscall.read(0x6, 0xc829b06000, 0x200, 0x200, 0xc829b06200, 0x0, 0x0)
/usr/local/go/src/syscall/zsyscall_linux_amd64.go:783 +0x5f
syscall.Read(0x6, 0xc829b06000, 0x200, 0x200, 0xc829b06000, 0x0, 0x0)
/usr/local/go/src/syscall/syscall_unix.go:161 +0x4d
os.(*File).read(0xc82a0faac8, 0xc829b06000, 0x200, 0x200, 0x7f4700000001, 0x0, 0x0)
/usr/local/go/src/os/file_unix.go:228 +0x53
os.(*File).Read(0xc82a0faac8, 0xc829b06000, 0x200, 0x200, 0x200, 0x0, 0x0)
/usr/local/go/src/os/file.go:95 +0x8a
bytes.(*Buffer).ReadFrom(0xc82026e8a0, 0x7f47d95dc1f8, 0xc82a0faac8, 0x0, 0x0, 0x0)
/usr/local/go/src/bytes/buffer.go:176 +0x23f
io/ioutil.readAll(0x7f47d95dc1f8, 0xc82a0faac8, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/io/ioutil/ioutil.go:33 +0x156
io/ioutil.ReadAll(0x7f47d95dc1f8, 0xc82a0faac8, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/io/ioutil/ioutil.go:42 +0x51