aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/proc.go4
-rw-r--r--src/runtime/runtime2.go1
-rw-r--r--src/runtime/stack.go3
-rw-r--r--src/runtime/traceruntime.go2
-rw-r--r--src/runtime/tracestack.go17
5 files changed, 23 insertions, 4 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 9817308430..0376f7812b 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -3307,10 +3307,10 @@ func execute(gp *g, inheritTime bool) {
tryRecordGoroutineProfile(gp, nil, osyield)
}
- // Assign gp.m before entering _Grunning so running Gs have an
- // M.
+ // Assign gp.m before entering _Grunning so running Gs have an M.
mp.curg = gp
gp.m = mp
+ gp.syncSafePoint = false // Clear the flag, which may have been set by morestack.
casgstatus(gp, _Grunnable, _Grunning)
gp.waitsince = 0
gp.preempt = false
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 96720846b2..49a2ba2752 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -466,6 +466,7 @@ type g struct {
runnableTime int64 // the amount of time spent runnable, cleared when running, only used when tracking
lockedm muintptr
fipsIndicator uint8
+ syncSafePoint bool // set if g is stopped at a synchronous safe point.
runningCleanups atomic.Bool
sig uint32
writebuf []byte
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index 4b647976f0..a338708d76 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -1115,6 +1115,9 @@ func newstack() {
shrinkstack(gp)
}
+ // Set a flag indicated that we've been synchronously preempted.
+ gp.syncSafePoint = true
+
if gp.preemptStop {
preemptPark(gp) // never returns
}
diff --git a/src/runtime/traceruntime.go b/src/runtime/traceruntime.go
index 39adeb4c07..a2775a3427 100644
--- a/src/runtime/traceruntime.go
+++ b/src/runtime/traceruntime.go
@@ -457,7 +457,7 @@ func (tl traceLocker) GoPreempt() {
// GoStop emits a GoStop event with the provided reason.
func (tl traceLocker) GoStop(reason traceGoStopReason) {
- tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoStop, traceArg(trace.goStopReasons[tl.gen%2][reason]), tl.stack(1))
+ tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoStop, traceArg(trace.goStopReasons[tl.gen%2][reason]), tl.stack(0))
}
// GoPark emits a GoBlock event with the provided reason.
diff --git a/src/runtime/tracestack.go b/src/runtime/tracestack.go
index bca2d0a88d..2ee68c85f0 100644
--- a/src/runtime/tracestack.go
+++ b/src/runtime/tracestack.go
@@ -109,7 +109,22 @@ func traceStack(skip int, gp *g, gen uintptr) uint64 {
nstk += 1 + fpTracebackPCs(unsafe.Pointer(gp.syscallbp), pcBuf[2:])
} else {
pcBuf[1] = gp.sched.pc
- nstk += 1 + fpTracebackPCs(unsafe.Pointer(gp.sched.bp), pcBuf[2:])
+ if gp.syncSafePoint {
+ // We're stopped in morestack, which is an odd state because gp.sched.bp
+ // refers to our parent frame, since we haven't had the chance to push our
+ // frame pointer to the stack yet. If we just start walking from gp.sched.bp,
+ // we'll skip a frame as a result. Luckily, we can find the PC we want right
+ // at gp.sched.sp on non-LR platforms, and we have it directly on LR platforms.
+ // See issue go.dev/issue/68090.
+ if usesLR {
+ pcBuf[2] = gp.sched.lr
+ } else {
+ pcBuf[2] = *(*uintptr)(unsafe.Pointer(gp.sched.sp))
+ }
+ nstk += 2 + fpTracebackPCs(unsafe.Pointer(gp.sched.bp), pcBuf[3:])
+ } else {
+ nstk += 1 + fpTracebackPCs(unsafe.Pointer(gp.sched.bp), pcBuf[2:])
+ }
}
}
}