]> Cypherpunks repositories - gostls13.git/commitdiff
runtime, internal/poll: report only critical event scanning error
authorMikio Hara <mikioh.public.networking@gmail.com>
Thu, 14 Mar 2019 20:10:08 +0000 (05:10 +0900)
committerMikio Hara <mikioh.public.networking@gmail.com>
Tue, 19 Mar 2019 08:30:50 +0000 (08:30 +0000)
This change makes the runtime-integrated network poller report only
critical event scanning errors.

In the previous attempt, CL 166497, we treated any combination of error
events as event scanning errors and it caused false positives in event
waiters because platform-dependent event notification mechanisms allow
event originators to use various combination of events.

To avoid false positives, this change makes the poller treat an
individual error event as a critical event scanning error by the
convention of event notification mechanism implementations.

Updates #30624.
Fixes #30817.
Fixes #30840.

Change-Id: I906c9e83864527ff73f636fd02bab854d54684ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/167777
Run-TryBot: Mikio Hara <mikioh.public.networking@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/internal/poll/error_test.go
src/internal/poll/read_test.go [new file with mode: 0644]
src/runtime/netpoll_aix.go
src/runtime/netpoll_epoll.go
src/runtime/netpoll_kqueue.go
src/runtime/netpoll_solaris.go

index 89c6e384c5448ade11d13c717a026cfe15fd5bf6..06b96f635a5762f55acd924201c9aec91d416a90 100644 (file)
@@ -9,6 +9,7 @@ import (
        "net"
        "os"
        "testing"
+       "time"
 )
 
 func TestReadError(t *testing.T) {
@@ -18,6 +19,11 @@ func TestReadError(t *testing.T) {
                        t.Skip(err)
                }
                defer f.Close()
+
+               // Give scheduler a chance to have two separated
+               // goroutines: an event poller and an event waiter.
+               time.Sleep(100 * time.Millisecond)
+
                var b [1]byte
                _, err = f.Read(b[:])
                if perr := parseReadError(err, isBadStateFileError); perr != nil {
diff --git a/src/internal/poll/read_test.go b/src/internal/poll/read_test.go
new file mode 100644 (file)
index 0000000..b4f5236
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package poll_test
+
+import (
+       "io/ioutil"
+       "os"
+       "runtime"
+       "sync"
+       "testing"
+       "time"
+)
+
+func TestRead(t *testing.T) {
+       t.Run("SpecialFile", func(t *testing.T) {
+               var wg sync.WaitGroup
+               for _, p := range specialFiles() {
+                       for i := 0; i < 4; i++ {
+                               wg.Add(1)
+                               go func(p string) {
+                                       defer wg.Done()
+                                       for i := 0; i < 100; i++ {
+                                               if _, err := ioutil.ReadFile(p); err != nil {
+                                                       t.Error(err)
+                                                       return
+                                               }
+                                               time.Sleep(time.Nanosecond)
+                                       }
+                               }(p)
+                       }
+               }
+               wg.Wait()
+       })
+}
+
+func specialFiles() []string {
+       var ps []string
+       switch runtime.GOOS {
+       case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
+               ps = []string{
+                       "/dev/null",
+               }
+       case "linux":
+               ps = []string{
+                       "/dev/null",
+                       "/proc/stat",
+                       "/sys/devices/system/cpu/online",
+               }
+       }
+       nps := ps[:0]
+       for _, p := range ps {
+               f, err := os.Open(p)
+               if err != nil {
+                       continue
+               }
+               f.Close()
+               nps = append(nps, p)
+       }
+       return nps
+}
index b4d7de8c2af53cd4288ef388b02b144b1764b327..0ad8718fe063a8bad787e0ab9672ab5f5e130db4 100644 (file)
@@ -233,7 +233,7 @@ retry:
                                println("*** netpollready i=", i, "revents=", pfd.revents, "events=", pfd.events, "pd=", pds[i])
                        }
                        pds[i].everr = false
-                       if pfd.revents&_POLLERR != 0 {
+                       if pfd.revents == _POLLERR {
                                pds[i].everr = true
                        }
                        netpollready(&toRun, pds[i], mode)
index 7dc8301acd87544339ad76c8ed66e647f594e8d5..8f49309865fb43a93fbcce21984c596959b02979 100644 (file)
@@ -92,7 +92,7 @@ retry:
                if mode != 0 {
                        pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
                        pd.everr = false
-                       if ev.events&_EPOLLERR != 0 {
+                       if ev.events == _EPOLLERR {
                                pd.everr = true
                        }
                        netpollready(&toRun, pd, mode)
index 1de484978a87b76256282501aae2c534360f22b6..a8880e82a5ae1c13dd30fe7d9f652b0a56e44a00 100644 (file)
@@ -104,7 +104,7 @@ retry:
                if mode != 0 {
                        pd := (*pollDesc)(unsafe.Pointer(ev.udata))
                        pd.everr = false
-                       if ev.flags&_EV_ERROR != 0 {
+                       if ev.flags == _EV_ERROR {
                                pd.everr = true
                        }
                        netpollready(&toRun, pd, mode)
index 7ae8a2aba10174a3ef97d7acf76a33fe04fcbed0..b4bb40ed9b04c4adc0697494128dc4fdf89d5e6c 100644 (file)
@@ -234,7 +234,7 @@ retry:
 
                if mode != 0 {
                        pd.everr = false
-                       if ev.portev_events&_POLLERR != 0 {
+                       if ev.portev_events == _POLLERR {
                                pd.everr = true
                        }
                        netpollready(&toRun, pd, mode)