proc: fix stacktraces on freebsd/amd64/go1.20 (#3458)

TestStacktraceGoroutine failed intermittently on freebsd/amd64/go1.20.

This happens because of two windows, in the scheduler (right after
parking a goroutine and just before resuming a parked goroutine) where
a thread is associated with a goroutine but running in the system stack
and there is no systemstack_switch frame to connect the two stacks.
This commit is contained in:
Alessandro Arzilli 2023-08-15 00:32:15 +02:00 committed by GitHub
parent ec07c27fc7
commit 281f3920dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 4 deletions

@ -200,11 +200,19 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
return true
case "runtime.goexit", "runtime.rt0_go", "runtime.mcall":
case "runtime.goexit", "runtime.rt0_go":
// Look for "top of stack" functions.
it.atend = true
return true
case "runtime.mcall":
if it.systemstack && it.g != nil {
it.switchToGoroutineStack()
return true
}
it.atend = true
return true
case "runtime.mstart":
// Calls to runtime.systemstack will switch to the systemstack then:
// 1. alter the goroutine stack so that it looks like systemstack_switch

@ -217,10 +217,19 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
return true
}
case "runtime.goexit", "runtime.rt0_go", "runtime.mcall":
case "runtime.goexit", "runtime.rt0_go":
// Look for "top of stack" functions.
it.atend = true
return true
case "runtime.mcall":
if it.systemstack && it.g != nil {
it.switchToGoroutineStack()
return true
}
it.atend = true
return true
case "crosscall2":
// The offsets get from runtime/cgo/asm_arm64.s:10
bpoff := uint64(14)

@ -127,11 +127,19 @@ func i386SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
switch it.frame.Current.Fn.Name {
case "runtime.asmcgocall", "runtime.cgocallback_gofunc": // TODO(chainhelen), need to support cgo stacktraces.
return false
case "runtime.goexit", "runtime.rt0_go", "runtime.mcall":
case "runtime.goexit", "runtime.rt0_go":
// Look for "top of stack" functions.
it.atend = true
return true
case "runtime.mcall":
if it.systemstack && it.g != nil {
it.switchToGoroutineStack()
return true
}
it.atend = true
return true
case "runtime.mstart":
// Calls to runtime.systemstack will switch to the systemstack then:
// 1. alter the goroutine stack so that it looks like systemstack_switch

@ -106,10 +106,17 @@ func ppc64leSwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) boo
switch it.frame.Current.Fn.Name {
case "runtime.asmcgocall", "runtime.cgocallback_gofunc", "runtime.sigpanic", "runtime.cgocallback":
//do nothing
case "runtime.goexit", "runtime.rt0_go", "runtime.mcall":
case "runtime.goexit", "runtime.rt0_go":
// Look for "top of stack" functions.
it.atend = true
return true
case "runtime.mcall":
if it.systemstack && it.g != nil {
it.switchToGoroutineStack()
return true
}
it.atend = true
return true
case "crosscall2":
//The offsets get from runtime/cgo/asm_ppc64x.s:10
newsp, _ := readUintRaw(it.mem, it.regs.SP()+8*24, int64(it.bi.Arch.PtrSize()))