diff options
| author | Michael Pratt <mpratt@google.com> | 2025-01-22 14:13:33 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-05-19 11:20:58 -0700 |
| commit | 11c86ddcb898f4c2c5fa548d46821ab76ea2d0fd (patch) | |
| tree | ca9ac5f4925510a0415c6e5953be1cc8f39b385f /src/runtime/testdata | |
| parent | bc5aa2f7d3e1deb5468432230c438a8a9e8de316 (diff) | |
| download | go-11c86ddcb898f4c2c5fa548d46821ab76ea2d0fd.tar.xz | |
runtime: check for gsignal in asancall/msancall/racecall
asancall and msancall are reachable from the signal handler, where we
are running on gsignal. Currently, these calls will use the g0 stack in
this case, but if the interrupted code was running on g0 this will
corrupt the stack and likely cause a crash.
As far as I know, racecall is not reachable from the signal handler, but
I have updated it as well for consistency.
This is the most straightforward fix, though it would be nice to
eventually migrate these wrappers to asmcgocall, which already handled
this case.
Fixes #71395.
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-asan-clang15,gotip-linux-amd64-msan-clang15,gotip-linux-amd64-race
Change-Id: I6a6a636ccba826dd53e31c0e85b5d42fb1e98d12
Reviewed-on: https://go-review.googlesource.com/c/go/+/643875
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/runtime/testdata')
| -rw-r--r-- | src/runtime/testdata/testprogcgo/tracebackctxt.go | 43 | ||||
| -rw-r--r-- | src/runtime/testdata/testprogcgo/tracebackctxt_c.c | 5 |
2 files changed, 48 insertions, 0 deletions
diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt.go b/src/runtime/testdata/testprogcgo/tracebackctxt.go index 62ff8eccd6..5b622c38a6 100644 --- a/src/runtime/testdata/testprogcgo/tracebackctxt.go +++ b/src/runtime/testdata/testprogcgo/tracebackctxt.go @@ -17,19 +17,24 @@ extern void tcTraceback(void*); extern void tcSymbolizer(void*); extern int getContextCount(void); extern void TracebackContextPreemptionCallGo(int); +extern void TracebackContextProfileCallGo(void); */ import "C" import ( "fmt" + "io" "runtime" + "runtime/pprof" "sync" + "sync/atomic" "unsafe" ) func init() { register("TracebackContext", TracebackContext) register("TracebackContextPreemption", TracebackContextPreemption) + register("TracebackContextProfile", TracebackContextProfile) } var tracebackOK bool @@ -134,3 +139,41 @@ func TracebackContextPreemptionGoFunction(i C.int) { // Do some busy work. fmt.Sprintf("%d\n", i) } + +// Regression test for issue 71395. +// +// The SIGPROF handler can call the SetCgoTraceback traceback function if the +// context function is also provided. Ensure that call is safe. +func TracebackContextProfile() { + runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContextSimple), unsafe.Pointer(C.tcSymbolizer)) + + if err := pprof.StartCPUProfile(io.Discard); err != nil { + panic(fmt.Sprintf("error starting CPU profile: %v", err)) + } + defer pprof.StopCPUProfile() + + const calls = 1e5 + var wg sync.WaitGroup + for i := 0; i < runtime.GOMAXPROCS(0); i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < calls; j++ { + C.TracebackContextProfileCallGo() + } + }() + } + wg.Wait() + + fmt.Println("OK") +} + +var sink atomic.Pointer[byte] + +//export TracebackContextProfileGoFunction +func TracebackContextProfileGoFunction() { + // Issue 71395 occurs when SIGPROF lands on code running on the system + // stack in a cgo callback. The allocator uses the system stack. + b := make([]byte, 128) + sink.Store(&b[0]) +} diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c index 910cb7b899..98b43038c5 100644 --- a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c +++ b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c @@ -12,6 +12,7 @@ extern void G1(void); extern void G2(void); extern void TracebackContextPreemptionGoFunction(int); +extern void TracebackContextProfileGoFunction(void); void C1() { G1(); @@ -101,3 +102,7 @@ void tcSymbolizer(void *parg) { void TracebackContextPreemptionCallGo(int i) { TracebackContextPreemptionGoFunction(i); } + +void TracebackContextProfileCallGo(void) { + TracebackContextProfileGoFunction(); +} |
