aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/testdata
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2025-01-22 14:13:33 -0500
committerGopher Robot <gobot@golang.org>2025-05-19 11:20:58 -0700
commit11c86ddcb898f4c2c5fa548d46821ab76ea2d0fd (patch)
treeca9ac5f4925510a0415c6e5953be1cc8f39b385f /src/runtime/testdata
parentbc5aa2f7d3e1deb5468432230c438a8a9e8de316 (diff)
downloadgo-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.go43
-rw-r--r--src/runtime/testdata/testprogcgo/tracebackctxt_c.c5
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();
+}