runtime: use a pipe to wake up signal_recv on Darwin

The implementation of semaphores, and therefore notes, used on Darwin
is not async-signal-safe. The runtime has one case where a note needs
to be woken up from a signal handler: the call to notewakeup in sigsend.
That notewakeup call is only called on a single note, and it doesn't
need the full functionality of notes: nothing ever does a timed wait on it.
So change that one note to use a different implementation on Darwin,
based on a pipe. This lets the wakeup code use the write call, which is
async-signal-safe.

Fixes #31264

Change-Id: If705072d7a961dd908ea9d639c8d12b222c64806
Reviewed-on: https://go-review.googlesource.com/c/go/+/184169
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Ian Lance Taylor 2019-06-28 11:20:15 -07:00
parent 623d653db7
commit c485e8b559
13 changed files with 159 additions and 0 deletions

View file

@ -105,6 +105,10 @@ Send:
break Send
case sigReceiving:
if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
if GOOS == "darwin" {
sigNoteWakeup(&sig.note)
break Send
}
notewakeup(&sig.note)
break Send
}
@ -136,6 +140,10 @@ func signal_recv() uint32 {
throw("signal_recv: inconsistent state")
case sigIdle:
if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
if GOOS == "darwin" {
sigNoteSleep(&sig.note)
break Receive
}
notetsleepg(&sig.note, -1)
noteclear(&sig.note)
break Receive
@ -188,6 +196,10 @@ func signal_enable(s uint32) {
// to use for initialization. It does not pass
// signal information in m.
sig.inuse = true // enable reception of signals; cannot disable
if GOOS == "darwin" {
sigNoteSetup(&sig.note)
return
}
noteclear(&sig.note)
return
}