internal/poll: avoid race between SetDeadline and timer expiry in Plan 9
The mutexes added by CL 235820 aren't sufficient to prevent a race when
an i/o deadline timer fires just as the deadline is being reset to zero.
Consider this possible sequence when goroutine S is clearing the
deadline and goroutine T has been started by the timer:
1. S locks the mutex
2. T blocks on the mutex
3. S sets the timedout flag to false
4. S calls Stop on the timer (and fails, because the timer has fired)
5. S unlocks the mutex
6. T locks the mutex
7. T sets the timedout flag to true
Now all subsequent I/O will timeout, although the deadline has been
cleared.
The fix is for the timeout goroutine to skip setting the timedout
flag if the timer pointer has been cleared, or reassigned by
another SetDeadline operation.
Fixes #57114
Change-Id: I4a45d19c3b4b66cdf151dcc3f70536deaa8216a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/470215
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David du Colombier <0intro@gmail.com> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>