aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/netpoll_kqueue.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2022-01-12 17:22:09 -0500
committerRuss Cox <rsc@golang.org>2022-01-14 17:49:58 +0000
commit17b2fb1b656a275906b5071c562439d50a27f167 (patch)
treef60646e797dbed14f7b8085c44c50ff4543f9c75 /src/runtime/netpoll_kqueue.go
parentb41185c5c3da2d5f52b3b5aa7eb034addd458938 (diff)
downloadgo-17b2fb1b656a275906b5071c562439d50a27f167.tar.gz
go-17b2fb1b656a275906b5071c562439d50a27f167.zip
runtime: fix net poll races
The netpoll code was written long ago, when the only multiprocessors that Go ran on were x86. It assumed that an atomic store would trigger a full memory barrier and then used that barrier to order otherwise racy access to a handful of fields, including pollDesc.closing. On ARM64, this code has finally failed, because the atomic store is on a value completely unrelated to any of the racily-accessed fields, and the ARMv8 hardware, unlike x86, is clever enough not to do a full memory barrier for a simple atomic store. We are seeing a constant background rate of trybot failures where the net/http tests deadlock - a netpollblock has clearly happened after the pollDesc has begun to close. The code that does the racy reads is netpollcheckerr, which needs to be able to run without acquiring a lock. This CL fixes the race, without introducing unnecessary inefficiency or deadlock, by arranging for every updater of the relevant fields to publish a summary as a single atomic uint32, and then having netpollcheckerr use a single atomic load to fetch the relevant bits and then proceed as before. Fixes #45211 (until proven otherwise!). Change-Id: Ib6788c8da4d00b7bda84d55ca3fdffb5a64c1a0a Reviewed-on: https://go-review.googlesource.com/c/go/+/378234 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Trust: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/netpoll_kqueue.go')
-rw-r--r--src/runtime/netpoll_kqueue.go5
1 files changed, 1 insertions, 4 deletions
diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go
index 2f7f2848d2..1694753b6f 100644
--- a/src/runtime/netpoll_kqueue.go
+++ b/src/runtime/netpoll_kqueue.go
@@ -179,10 +179,7 @@ retry:
}
if mode != 0 {
pd := (*pollDesc)(unsafe.Pointer(ev.udata))
- pd.everr = false
- if ev.flags == _EV_ERROR {
- pd.everr = true
- }
+ pd.setEventErr(ev.flags == _EV_ERROR)
netpollready(&toRun, pd, mode)
}
}