aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/os_darwin.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-06-28 11:20:15 -0700
committerIan Lance Taylor <iant@golang.org>2019-06-30 05:48:31 +0000
commitc485e8b55918b3b37e6eab47036ab6f16fec226d (patch)
treed2c8dfa28092ff8c715c817a9e9574e076906669 /src/runtime/os_darwin.go
parent623d653db7cd2287305347196f7f4742b6b1fb38 (diff)
downloadgo-c485e8b55918b3b37e6eab47036ab6f16fec226d.tar.gz
go-c485e8b55918b3b37e6eab47036ab6f16fec226d.zip
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>
Diffstat (limited to 'src/runtime/os_darwin.go')
-rw-r--r--src/runtime/os_darwin.go46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index 819aaaca70..1614b66c8a 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -75,6 +75,52 @@ func semawakeup(mp *m) {
pthread_mutex_unlock(&mp.mutex)
}
+// The read and write file descriptors used by the sigNote functions.
+var sigNoteRead, sigNoteWrite int32
+
+// sigNoteSetup initializes an async-signal-safe note.
+//
+// The current implementation of notes on Darwin is not async-signal-safe,
+// because the functions pthread_mutex_lock, pthread_cond_signal, and
+// pthread_mutex_unlock, called by semawakeup, are not async-signal-safe.
+// There is only one case where we need to wake up a note from a signal
+// handler: the sigsend function. The signal handler code does not require
+// all the features of notes: it does not need to do a timed wait.
+// This is a separate implementation of notes, based on a pipe, that does
+// not support timed waits but is async-signal-safe.
+func sigNoteSetup(*note) {
+ if sigNoteRead != 0 || sigNoteWrite != 0 {
+ throw("duplicate sigNoteSetup")
+ }
+ var errno int32
+ sigNoteRead, sigNoteWrite, errno = pipe()
+ if errno != 0 {
+ throw("pipe failed")
+ }
+ closeonexec(sigNoteRead)
+ closeonexec(sigNoteWrite)
+
+ // Make the write end of the pipe non-blocking, so that if the pipe
+ // buffer is somehow full we will not block in the signal handler.
+ // Leave the read end of the pipe blocking so that we will block
+ // in sigNoteSleep.
+ setNonblock(sigNoteWrite)
+}
+
+// sigNoteWakeup wakes up a thread sleeping on a note created by sigNoteSetup.
+func sigNoteWakeup(*note) {
+ var b byte
+ write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
+}
+
+// sigNoteSleep waits for a note created by sigNoteSetup to be woken.
+func sigNoteSleep(*note) {
+ entersyscallblock()
+ var b byte
+ read(sigNoteRead, unsafe.Pointer(&b), 1)
+ exitsyscall()
+}
+
// BSD interface for threading.
func osinit() {
// pthread_create delayed until end of goenvs so that we