n, err := syscall.Read(fd.Sysfd, p)
if err != nil {
n = 0
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitRead(fd.isFile); err == nil {
continue
}
n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0)
if err != nil {
n = 0
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitRead(fd.isFile); err == nil {
continue
}
n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0)
if err != nil {
// TODO(dfc) should n and oobn be set to 0
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitRead(fd.isFile); err == nil {
continue
}
if nn == len(p) {
return nn, err
}
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitWrite(fd.isFile); err == nil {
continue
}
}
for {
err := syscall.Sendto(fd.Sysfd, p, 0, sa)
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitWrite(fd.isFile); err == nil {
continue
}
}
for {
n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0)
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitWrite(fd.isFile); err == nil {
continue
}
}
switch err {
case syscall.EAGAIN:
- if err = fd.pd.waitRead(fd.isFile); err == nil {
- continue
+ if fd.pd.pollable() {
+ if err = fd.pd.waitRead(fd.isFile); err == nil {
+ continue
+ }
}
case syscall.ECONNABORTED:
// This means that a socket on the listen
n, err := syscall.ReadDirent(fd.Sysfd, buf)
if err != nil {
n = 0
- if err == syscall.EAGAIN {
+ if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitRead(fd.isFile); err == nil {
continue
}
func TestClosedPipeRaceWrite(t *testing.T) {
testClosedPipeRace(t, false)
}
+
+// Issue 20915: Reading on nonblocking fd should not return "waiting
+// for unsupported file type." Currently it returns EAGAIN; it is
+// possible that in the future it will simply wait for data.
+func TestReadNonblockingFd(t *testing.T) {
+ if os.Getenv("GO_WANT_READ_NONBLOCKING_FD") == "1" {
+ fd := int(os.Stdin.Fd())
+ syscall.SetNonblock(fd, true)
+ defer syscall.SetNonblock(fd, false)
+ _, err := os.Stdin.Read(make([]byte, 1))
+ if err != nil {
+ if perr, ok := err.(*os.PathError); !ok || perr.Err != syscall.EAGAIN {
+ t.Fatalf("read on nonblocking stdin got %q, should have gotten EAGAIN", err)
+ }
+ }
+ os.Exit(0)
+ }
+
+ testenv.MustHaveExec(t)
+ r, w, err := os.Pipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ defer w.Close()
+ cmd := osexec.Command(os.Args[0], "-test.run="+t.Name())
+ cmd.Env = append(os.Environ(), "GO_WANT_READ_NONBLOCKING_FD=1")
+ cmd.Stdin = r
+ output, err := cmd.CombinedOutput()
+ t.Logf("%s", output)
+ if err != nil {
+ t.Errorf("child process failed: %v", err)
+ }
+}