-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
What version of Go are you using (go version)?
$ go version go version devel +9eef49cfa6eb016e3b20df189e540c6c5a71f365 2021-01-04 17:59:30 +0000 +0000 plan9/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
amd64/plan9 (only 9front)
What did you do?
Run this program:
package main
import (
"bytes"
"os"
"os/exec"
)
func main() {
var buf bytes.Buffer
buf.WriteString("hello world\n")
cmd := exec.Command("/bin/cat")
cmd.Stdin = &buf
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
}What did you expect to see?
No hang
What did you see instead?
Program hangs trying to read from stdin, and also the parent process hangs trying to read error string from the child. Speaking to 9front devs, this seems to be due to a recent change in how OCEXEC flag works. The OCEXEC flag semantics have been changed to refer to the file descriptor instead of the channel.
Note: you can only reproduce this when stdin is a pipe. It doesn't hang if the stdin is a disk file. So, there are two pipes involved here. One is created by os/exec to write to program stdin, and the other pipe is used by the syscall package to read error string from the child. The write end of the pipe created by syscall is marked closed-on-exec. Since the close-on-exec is no longer set correctly on 9front, we hang trying to read the error string from the child. Write to stdin pipe also likely hangs due to this.
It's possible to add a workaround which works on both 9front and 9legacy.
@gopherbot Add labels OS-Plan9, NeedsFix