Skip to content

Commit 6634ce2

Browse files
dr2chasegopherbot
authored andcommitted
[release-branch.go1.21] runtime: profiling on Darwin cannot use blocking reads
On Darwin (and assume also on iOS but not sure), notetsleepg cannot be called in a signal-handling context. Avoid this by disabling block reads on Darwin. An alternate approach was to add "sigNote" with a pipe-based implementation on Darwin, but that ultimately would have required at least one more linkname between runtime and syscall to avoid racing with fork and opening the pipe, so, not. Fixes #62019. Updates #61768. Change-Id: I0e8dd4abf9a606a3ff73fc37c3bd75f55924e07e Reviewed-on: https://go-review.googlesource.com/c/go/+/518836 Run-TryBot: David Chase <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> (cherry picked from commit c6ee8e3) Reviewed-on: https://go-review.googlesource.com/c/go/+/519375 Reviewed-by: Austin Clements <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]>
1 parent 25c6dce commit 6634ce2

File tree

3 files changed

+8
-2
lines changed

3 files changed

+8
-2
lines changed

src/runtime/cpuprof.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) {
227227
lock(&cpuprof.lock)
228228
log := cpuprof.log
229229
unlock(&cpuprof.lock)
230-
data, tags, eof := log.read(profBufBlocking)
230+
readMode := profBufBlocking
231+
if GOOS == "darwin" || GOOS == "ios" {
232+
readMode = profBufNonBlocking // For #61768; on Darwin notes are not async-signal-safe. See sigNoteSetup in os_darwin.go.
233+
}
234+
data, tags, eof := log.read(readMode)
231235
if len(data) == 0 && eof {
232236
lock(&cpuprof.lock)
233237
cpuprof.log = nil

src/runtime/os_darwin.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func semawakeup(mp *m) {
8181
// The read and write file descriptors used by the sigNote functions.
8282
var sigNoteRead, sigNoteWrite int32
8383

84-
// sigNoteSetup initializes an async-signal-safe note.
84+
// sigNoteSetup initializes a single, there-can-only-be-one, async-signal-safe note.
8585
//
8686
// The current implementation of notes on Darwin is not async-signal-safe,
8787
// because the functions pthread_mutex_lock, pthread_cond_signal, and
@@ -93,6 +93,7 @@ var sigNoteRead, sigNoteWrite int32
9393
// not support timed waits but is async-signal-safe.
9494
func sigNoteSetup(*note) {
9595
if sigNoteRead != 0 || sigNoteWrite != 0 {
96+
// Generalizing this would require avoiding the pipe-fork-closeonexec race, which entangles syscall.
9697
throw("duplicate sigNoteSetup")
9798
}
9899
var errno int32

src/runtime/profbuf.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ Read:
491491
// Nothing to read right now.
492492
// Return or sleep according to mode.
493493
if mode == profBufNonBlocking {
494+
// Necessary on Darwin, notetsleepg below does not work in signal handler, root cause of #61768.
494495
return nil, nil, false
495496
}
496497
if !b.w.cas(bw, bw|profReaderSleeping) {

0 commit comments

Comments
 (0)