aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-03-06 14:12:45 -0800
committerIan Lance Taylor <iant@golang.org>2018-03-06 23:21:25 +0000
commit558769a61b246464f979f3f4d370dad96cee2109 (patch)
treeb0efbd840819eaed6357d7a3a2ebdd3efab9704b /src
parent42ecf39e85a6960f4e0c2272bf9aff491eda3b66 (diff)
downloadgo-558769a61b246464f979f3f4d370dad96cee2109.tar.xz
internal/poll: if poller init fails, assume blocking mode
Fixes #23943 Change-Id: I16e604872f1615963925ec3c4710106bcce1330c Reviewed-on: https://go-review.googlesource.com/99015 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/internal/poll/fd_unix.go8
-rw-r--r--src/os/timeout_test.go33
2 files changed, 40 insertions, 1 deletions
diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go
index 372dc81633..36376ef6cb 100644
--- a/src/internal/poll/fd_unix.go
+++ b/src/internal/poll/fd_unix.go
@@ -59,7 +59,13 @@ func (fd *FD) Init(net string, pollable bool) error {
fd.isBlocking = true
return nil
}
- return fd.pd.init(fd)
+ err := fd.pd.init(fd)
+ if err != nil {
+ // If we could not initialize the runtime poller,
+ // assume we are using blocking mode.
+ fd.isBlocking = true
+ }
+ return err
}
// Destroy closes the file descriptor. This is called when there are
diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go
index 6f47ed04a9..6105f9b1a1 100644
--- a/src/os/timeout_test.go
+++ b/src/os/timeout_test.go
@@ -587,3 +587,36 @@ func TestRacyWrite(t *testing.T) {
}()
}
}
+
+// Closing a TTY while reading from it should not hang. Issue 23943.
+func TestTTYClose(t *testing.T) {
+ f, err := os.Open("/dev/tty")
+ if err != nil {
+ t.Skipf("skipping because opening /dev/tty failed: %v", err)
+ }
+
+ go func() {
+ var buf [1]byte
+ f.Read(buf[:])
+ }()
+
+ // Give the goroutine a chance to enter the read.
+ // It doesn't matter much if it occasionally fails to do so,
+ // we won't be testing what we want to test but the test will pass.
+ time.Sleep(time.Millisecond)
+
+ c := make(chan bool)
+ go func() {
+ defer close(c)
+ f.Close()
+ }()
+
+ select {
+ case <-c:
+ case <-time.After(time.Second):
+ t.Error("timed out waiting for close")
+ }
+
+ // On some systems the goroutines may now be hanging.
+ // There's not much we can do about that.
+}