]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.21] runtime: profiling on Darwin cannot use blocking reads
authorDavid Chase <drchase@google.com>
Fri, 11 Aug 2023 18:38:19 +0000 (14:38 -0400)
committerGopher Robot <gobot@golang.org>
Thu, 17 Aug 2023 21:10:08 +0000 (21:10 +0000)
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 <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit c6ee8e31e3e7b01da54d241ae5a8eed350ab0e9f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/519375
Reviewed-by: Austin Clements <austin@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>

src/runtime/cpuprof.go
src/runtime/os_darwin.go
src/runtime/profbuf.go

index 6ef374eaa429ad9ae9368688fbc1b94dd618cd32..0d7eeacb39923ba416515ee732fb2b78f7d98365 100644 (file)
@@ -227,7 +227,11 @@ func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) {
        lock(&cpuprof.lock)
        log := cpuprof.log
        unlock(&cpuprof.lock)
-       data, tags, eof := log.read(profBufBlocking)
+       readMode := profBufBlocking
+       if GOOS == "darwin" || GOOS == "ios" {
+               readMode = profBufNonBlocking // For #61768; on Darwin notes are not async-signal-safe.  See sigNoteSetup in os_darwin.go.
+       }
+       data, tags, eof := log.read(readMode)
        if len(data) == 0 && eof {
                lock(&cpuprof.lock)
                cpuprof.log = nil
index c4f3bb6a818585ca78284c39cc4011fbeaabe141..105de47a1f53bfd27a472502749dc17a76d3464f 100644 (file)
@@ -81,7 +81,7 @@ func semawakeup(mp *m) {
 // The read and write file descriptors used by the sigNote functions.
 var sigNoteRead, sigNoteWrite int32
 
-// sigNoteSetup initializes an async-signal-safe note.
+// sigNoteSetup initializes a single, there-can-only-be-one, 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
@@ -93,6 +93,7 @@ var sigNoteRead, sigNoteWrite int32
 // not support timed waits but is async-signal-safe.
 func sigNoteSetup(*note) {
        if sigNoteRead != 0 || sigNoteWrite != 0 {
+               // Generalizing this would require avoiding the pipe-fork-closeonexec race, which entangles syscall.
                throw("duplicate sigNoteSetup")
        }
        var errno int32
index c579f214887cffb7c2c4681e07f21e56456dea7a..083b55a9229d4bf5133d435975c72317ae12da4f 100644 (file)
@@ -491,6 +491,7 @@ Read:
                // Nothing to read right now.
                // Return or sleep according to mode.
                if mode == profBufNonBlocking {
+                       // Necessary on Darwin, notetsleepg below does not work in signal handler, root cause of #61768.
                        return nil, nil, false
                }
                if !b.w.cas(bw, bw|profReaderSleeping) {