Skip to content

runtime/pprof: theoretical appendLocsForStack panic with SIGPROF between cgocallback and exitsyscall #70529

Open

Description

@prattmic

runtime/pprof.appendLocsForStack asserts that an inline-expanded PC always expands to the same number of logical PCs (inlined frames). This is a static property of a given PC, so it should always be true.

When handling SIGPROF, if we are on an extra M running in C, we don't try to traceback since this is C anyway, and just add a sample with stack {pc, runtime._ExternalCode}.

"We are on an extra M running in C" is defined as gp.m.isExtraInC. In cgocallbackg, we clear this field after exitsyscall returns. This leaves a fairly long window when we are in fact running Go code, but the SIGPROF handler will think it is in C.

A lot of this code (particularly in exitsyscall) is reachable from normal Go code as well. If any of this code has more than 2 inlined frames at a single PC, then a SIGPROF from a normal Go context followed by a SIGPROF in this cgocallback context could trigger this appendLocsForStack panic.

I do not know if any code reachable in this window actually has more than 2 inlined frames. Only 2 frames is insufficient, as appendLocsForStack wouldn't actually care that the second frame is runtime._ExternalCode instead of the proper frame.

One potential fix is to attempt to do inline expansion in sigprofNonGoPC in case it actually is a Go PC.

Activity

  1. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Nov 22, 2024
  2. added this to the Go1.25 milestone on Nov 22, 2024
  3. self-assigned this
    on Nov 22, 2024
  4. nsrip-dd commented on Feb 19, 2025

    @nsrip-dd
    Member

    I believe we're seeing this problem in one of our programs. We're using the Apache Arrow Go client library, which has C (and also maybe C++?) code that calls back into Go. I think it also calls Go from C on "extra" Ms, based on seeing samples in a CPU profile where cgocallback is the root frame. We've seen panics like this, on Go 1.23.6:

    panic: runtime error: slice bounds out of range [3:2]
    
    goroutine 216489 [running]:
    runtime/pprof.(*profileBuilder).appendLocsForStack(0x401d2c2000, {0x4026ff9e00, 0x0, 0x40}, {0x402cf99df8?, 0x7?, 0x40?})
            /usr/local/go/src/runtime/pprof/proto.go:443 +0x8bc
    runtime/pprof.(*profileBuilder).build(0x401d2c2000)
            /usr/local/go/src/runtime/pprof/proto.go:376 +0x314
    runtime/pprof.profileWriter({0x634c1a0?, 0x4025122630?})
            /usr/local/go/src/runtime/pprof/pprof.go:882 +0xc4
    created by runtime/pprof.StartCPUProfile in goroutine 216360
            /usr/local/go/src/runtime/pprof/pprof.go:853 +0x184
    

    I unfortunately don't have the exact PC it's failing to handle. But I do see in CPU profiles for the program that this call to casgstatus in exitsyscall is inlined, and there's a CompareAndSwap inlined into that call:

    2157: 0x598fcc M=1 internal/runtime/atomic.(*Uint32).CompareAndSwap /usr/local/go/src/internal/runtime/atomic/types.go:236:0 s=235
                 runtime.casgstatus /usr/local/go/src/runtime/proc.go:1193:0 s=1175
                 runtime.exitsyscall /usr/local/go/src/runtime/proc.go:4661:0 s=4618
    

    So I think we meet the conditions described in this issue.

  5. prattmic commented on Feb 21, 2025

    @prattmic
    MemberAuthor

    I filed this issue when investigating one of these appendLocsForStack panics. I came up with this theoretical problem, though it ended up not being the cause of my crash.

    For that crash, I modified sigprofNonGoPC to throw if the PC actually is a Go PC.

    Something like

    func sigprofNonGoPC(pc uintptr, info *siginfo, ctx unsafe.Pointer) {
    	if prof.hz.Load() != 0 {
    		stk := []uintptr{
    			pc,
    			abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum,
    		}
    		cpuprof.addNonGo(stk)
    
    		fi := findfunc(pc)
    		if fi.valid() {
    			name := funcname(fi)
    			if name == "runtime.futex" {
    				// cgocallbackg -> exitsyscall -> stoplockedm -> futex actually occurs fairly often
    				return
    			}
    
    			println("runtime: SIGPROF on Go PC", hex(pc), "name", name)
    			println("runtime: siginfo", info, "ctx", ctx)
    			c := &sigctxt{info, ctx}
    			dumpregs(c)
    
    			// Extra debugging dumps as desired.
    
    			throw("SIGPROF on Go PC without G/M")
    		}
    	}
    }

    If you can reproduce, something like this might be useful as you can catch the problem at the moment it occurs rather than much later when the panic occurs.

  6. modified the milestones: Go1.25, Go1.26 on Aug 12, 2025
  7. dudusmida commented on Aug 22, 2025

    @dudusmida

    go1.25 still panic, but only with panic information is

    panic: stack too short to match cached location; stk = [0x4bf3c0 0x4c0ac1], l.pcs = [0x4bf3c0 0x4bf3c1 0x4bf3c7], original stk = [0x4bf3c0 0x4c0ac1]
    
    goroutine 387277268 [running]:
    runtime/pprof.(*profileBuilder).appendLocsForStack(0xc072d96dc0, {0xc002c3c500, 0x0, 0x20}, {0xc04b880ec8, 0x2, 0x2})
            /usr/local/go/src/runtime/pprof/proto.go:445 +0x8b4
    runtime/pprof.(*profileBuilder).build(0xc072d96dc0)
            /usr/local/go/src/runtime/pprof/proto.go:376 +0x377
    runtime/pprof.profileWriter({0x1ce2660?, 0xc0002a4570?})
            /usr/local/go/src/runtime/pprof/pprof.go:885 +0xaf
    created by runtime/pprof.StartCPUProfile in goroutine 65
            /usr/local/go/src/runtime/pprof/pprof.go:856 +0x136
    

    it seems that it is still the same problem.

    go1.25-commit: 89228ca

    for len(stk) > 0 {
    @@ -440,6 +441,9 @@ func (b *profileBuilder) appendLocsForStack(locs []uint64, stk []uintptr) (newLo
    			// Even if stk was truncated due to the stack depth
    			// limit, expandFinalInlineFrame above has already
    			// fixed the truncation, ensuring it is long enough.
    			if len(l.pcs) > len(stk) {
    				panic(fmt.Sprintf("stack too short to match cached location; stk = %#x, l.pcs = %#x, original stk = %#x", stk, l.pcs, origStk))
    			}
    			stk = stk[len(l.pcs):]
    			continue
    		}
    
  8. prattmic commented on Sep 10, 2025

    @prattmic
    MemberAuthor

    @dudusmida If you still have the binary, could you disassemble it (go tool objdump) and copy the function(s) containing the addresses in stk = [0x4bf3c0 0x4c0ac1], l.pcs = [0x4bf3c0 0x4bf3c1 0x4bf3c7]?

  9. harshavardhana commented on Nov 12, 2025

    @harshavardhana
    Contributor

    @prattmic got bit by this recently with MinIO compiled with some RDMA/Shared library dependencies while performing a CPU profile

    coe04: Nov 12 04:07:47 coe04 minio[372547]: panic: stack too short to match cached location; stk = [0x45bf20 0x45d681], l.pcs = [0x45bf20 0x45bf21 0x45bf27], original stk = [0x45bf20 
    0x45d681]
    coe04: Nov 12 04:07:47 coe04 minio[372547]: goroutine 48119722 [running]:
    coe04: Nov 12 04:07:47 coe04 minio[372547]: runtime/pprof.(*profileBuilder).appendLocsForStack(0xc5ae4b89a0, {0xc5399fd600, 0x0, 0x40}, {0xc71db22848, 0x2, 0x2})
    coe04: Nov 12 04:07:47 coe04 minio[372547]:         /home/harsha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.4.linux-amd64/src/runtime/pprof/proto.go:448 +0x8b4
    coe04: Nov 12 04:07:47 coe04 minio[372547]: runtime/pprof.(*profileBuilder).build(0xc5ae4b89a0)
    coe04: Nov 12 04:07:47 coe04 minio[372547]:         /home/harsha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.4.linux-amd64/src/runtime/pprof/proto.go:376 +0x365
    coe04: Nov 12 04:07:47 coe04 minio[372547]: runtime/pprof.profileWriter({0x7cd36c0?, 0xc64f2cbe90?})
    coe04: Nov 12 04:07:47 coe04 minio[372547]:         /home/harsha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.4.linux-amd64/src/runtime/pprof/pprof.go:877 +0xaf
    coe04: Nov 12 04:07:47 coe04 minio[372547]: created by runtime/pprof.StartCPUProfile in goroutine 47655287
    coe04: Nov 12 04:07:47 coe04 minio[372547]:         /home/harsha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.4.linux-amd64/src/runtime/pprof/pprof.go:848 +0x136
    

    The addresses 0x45bf20, 0x45bf21, and 0x45bf27 are all within runtime.exitsyscallfast:

    │                                                                                                                                                                                            │
    │ ```                                                                                                                                                                                        │
    │ TEXT runtime.exitsyscallfast(SB) /home/harsha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.4.linux-amd64/src/runtime/proc.go                                                              │
    │   proc.go:4887		0x45bf00		55			PUSHQ BP                                                                                                                                                    │
    │   proc.go:4887		0x45bf01		4889e5			MOVQ SP, BP                                                                                                                                             │
    │   proc.go:4887		0x45bf04		4883ec38		SUBQ $0x38, SP                                                                                                                                         │
    │   proc.go:4889		0x45bf08		813d0afd740bffffff7f	CMPL runtime.sched+252(SB), $0x7fffffff                                                                                                     │
    │   proc.go:4889		0x45bf12		0f848c010000		JE 0x45c0a4                                                                                                                                        │
    │   traceruntime.go:151	0x45bf18		803df1f9730b00		CMPB runtime.trace+1648(SB), $0x0                                                                                                          │
    │   traceruntime.go:151	0x45bf1f		90			NOPL                                                                                                                                                  │
    │   traceruntime.go:188	0x45bf20		7506			JNE 0x45bf28		<-- PC 0x45bf20                                                                                                                       │
    │   traceruntime.go:188	0x45bf22		31db			XORL BX, BX		<-- PC 0x45bf21 (byte within instruction)                                                                                              │
    │   traceruntime.go:188	0x45bf24		31c9			XORL CX, CX                                                                                                                                         │
    │   proc.go:4894		0x45bf26		eb12			JMP 0x45bf3a		<-- PC 0x45bf27 (byte within instruction)                                                                                                   │
    │   proc.go:4889		0x45bf28		4889442448		MOVQ AX, 0x48(SP)                                                                                                                                    │
    │   traceruntime.go:191	0x45bf2d		e88efe0100		CALL runtime.traceAcquireEnabled(SB)                                                                                                           │
    │   proc.go:4894		0x45bf32		4889c1			MOVQ AX, CX                                                                                                                                             │
    │   proc.go:4895		0x45bf35		488b442448		MOVQ 0x48(SP), AX                                                                                                                                    │
    │   proc.go:4895		0x45bf3a		4885c0			TESTQ AX, AX                                                                                                                                            │
    │   proc.go:4895		0x45bf3d		7423			JE 0x45bf62                                                                                                                                               │
    │   proc.go:4895		0x45bf3f		83780402		CMPL 0x4(AX), $0x2                                                                                                                                     │
    │   proc.go:4895		0x45bf43		7515			JNE 0x45bf5a                                                                                                                                              │
    │   proc.go:4889		0x45bf45		4889c2			MOVQ AX, DX                                                                                                                                             │
    │   proc.go:4895		0x45bf48		b802000000		MOVL $0x2, AX                                                                                                                                        │
    │   proc.go:4895		0x45bf4d		31f6			XORL SI, SI                                                                                                                                               │
    │   proc.go:4895		0x45bf4f		f00fb17204		LOCK CMPXCHGL SI, 0x4(DX)                                                                                                                            │
    │   proc.go:4895		0x45bf54		400f94c6		SETE SI                                                                                                                                                │
    │   proc.go:4895		0x45bf58		eb0d			JMP 0x45bf67                                                                                                                                              │
    │   proc.go:4897		0x45bf5a		4889c2			MOVQ AX, DX                                                                                                                                             │
    │   proc.go:4897		0x45bf5d		31f6			XORL SI, SI                                                                                                                                               │
    │   proc.go:4897		0x45bf5f		90			NOPL                                                                                                                                                        │
    │   proc.go:4895		0x45bf60		eb05			JMP 0x45bf67                                                                                                                                              │
    │   proc.go:4897		0x45bf62		4889c2			MOVQ AX, DX                                                                                                                                             │
    │   proc.go:4897		0x45bf65		31f6			XORL SI, SI                                                                                                                                               │
    │   proc.go:4895		0x45bf67		4084f6			TESTL SI, SI                                                                                                                                            │
    │   proc.go:4895		0x45bf6a		0f85ae000000		JNE 0x45c01e                                                                                                                                       │
    │   traceruntime.go:252	0x45bf70		4885db			TESTQ BX, BX                                                                                                                                      │
    │   proc.go:4904		0x45bf73		744f			JE 0x45bfc4                                                                                                                                               │
    │   traceruntime.go:261	0x45bf75		8b9130030000		MOVL 0x330(CX), DX                                                                                                                           │
    │   proc.go:4905		0x45bf7b		90			NOPL                                                                                                                                                        │
    │   proc.go:4905		0x45bf7c		0f1f4000		NOPL 0(AX)                                                                                                                                             │
    │   traceruntime.go:261	0x45bf80		85d2			TESTL DX, DX                                                                                                                                        │
    │   traceruntime.go:261	0x45bf82		760a			JBE 0x45bf8e                                                                                                                                        │
    │   traceruntime.go:262	0x45bf84		ffca			DECL DX                                                                                                                                             │
    │   traceruntime.go:262	0x45bf86		899130030000		MOVL DX, 0x330(CX)                                                                                                                           │
    │   traceruntime.go:262	0x45bf8c		eb0f			JMP 0x45bf9d                                                                                                                                        │
    │   traceruntime.go:264	0x45bf8e		90			NOPL                                                                                                                                                  │
    │   types.go:420		0x45bf8f		ba01000000		MOVL $0x1, DX                                                                                                                                        │
    │   types.go:420		0x45bf94		f0480fc19100030000	LOCK XADDQ DX, 0x300(CX)                                                                                                                      │
    │   runtime1.go:637	0x45bf9d		8b9100010000		MOVL 0x100(CX), DX                                                                                                                               │
    │   runtime1.go:637	0x45bfa3		8d5aff			LEAL -0x1(DX), BX                                                                                                                                     │
    │   traceruntime.go:270	0x45bfa6		90			NOPL                                                                                                                                                  │
    │   runtime1.go:637	0x45bfa7		899900010000		MOVL BX, 0x100(CX)                                                                                                                               │
    │   runtime1.go:638	0x45bfad		83fa01			CMPL DX, $0x1                                                                                                                                         │
    │   runtime1.go:638	0x45bfb0		7512			JNE 0x45bfc4                                                                                                                                            │
    │   runtime1.go:638	0x45bfb2		4180beb100000000	CMPB 0xb1(R14), $0x0                                                                                                                          │
    │   runtime1.go:638	0x45bfba		7408			JE 0x45bfc4                                                                                                                                             │
    │   runtime1.go:640	0x45bfbc		49c74610defaffff	MOVQ $-0x522, 0x10(R14)                                                                                                                       │
    │   proc.go:4909		0x45bfc4		48833dacfb740b00	CMPQ runtime.sched+88(SB), $0x0                                                                                                                 │
    │   proc.go:4909		0x45bfcc		743d			JE 0x45c00b                                                                                                                                               │
    │   proc.go:4910		0x45bfce		c644241700		MOVB $0x0, 0x17(SP)                                                                                                                                  │
    │   proc.go:4911		0x45bfd3		488d05e6000000		LEAQ runtime.exitsyscallfast.func1(SB), AX                                                                                                       │
    │   proc.go:4911		0x45bfda		4889442428		MOVQ AX, 0x28(SP)                                                                                                                                    │
    │   proc.go:4911		0x45bfdf		488d442417		LEAQ 0x17(SP), AX                                                                                                                                    │
    │   proc.go:4911		0x45bfe4		4889442430		MOVQ AX, 0x30(SP)                                                                                                                                    │
    │   proc.go:4911		0x45bfe9		488d442428		LEAQ 0x28(SP), AX                                                                                                                                    │
    │   proc.go:4911		0x45bfee		48890424		MOVQ AX, 0(SP)                                                                                                                                         │
    │   proc.go:4911		0x45bff2		e8a93f0300		CALL runtime.systemstack.abi0(SB)                                                                                                                    │
    │   proc.go:4911		0x45bff7		450f57ff		XORPS X15, X15                                                                                                                                         │
    │   proc.go:4911		0x45bffb		644c8b3425f8ffffff	MOVQ FS:0xfffffff8, R14                                                                                                                       │
    │   proc.go:4914		0x45c004		807c241700		CMPB 0x17(SP), $0x0                                                                                                                                  │
    │   proc.go:4914		0x45c009		7508			JNE 0x45c013                                                                                                                                              │
    │   proc.go:4918		0x45c00b		31c0			XORL AX, AX                                                                                                                                               │
    │   proc.go:4918		0x45c00d		4883c438		ADDQ $0x38, SP                                                                                                                                         │
    │   proc.go:4918		0x45c011		5d			POPQ BP                                                                                                                                                     │
    │   proc.go:4918		0x45c012		c3			RET                                                                                                                                                         │
    │   proc.go:4915		0x45c013		b801000000		MOVL $0x1, AX                                                                                                                                        │
    │   proc.go:4915		0x45c018		4883c438		ADDQ $0x38, SP                                                                                                                                         │
    │   proc.go:4915		0x45c01c		5d			POPQ BP                                                                                                                                                     │
    │   proc.go:4915		0x45c01d		c3			RET                                                                                                                                                         │
    │   proc.go:4894		0x45c01e		48895c2418		MOVQ BX, 0x18(SP)                                                                                                                                    │
    │   proc.go:4894		0x45c023		48894c2420		MOVQ CX, 0x20(SP)                                                                                                                                    │
    │   proc.go:4897		0x45c028		4889d0			MOVQ DX, AX                                                                                                                                             │
    │   proc.go:4897		0x45c02b		e8702c0000		CALL runtime.wirep(SB)                                                                                                                               │
    │   proc.go:4898		0x45c030		488b442420		MOVQ 0x20(SP), AX                                                                                                                                    │
    │   proc.go:4898		0x45c035		488b5c2418		MOVQ 0x18(SP), BX                                                                                                                                    │
    │   proc.go:4898		0x45c03a		e8c1000000		CALL runtime.exitsyscallfast_reacquired(SB)                                                                                                          │
    │   traceruntime.go:252	0x45c03f		488b4c2418		MOVQ 0x18(SP), CX                                                                                                                              │
    │   traceruntime.go:252	0x45c044		4885c9			TESTQ CX, CX                                                                                                                                      │
    │   proc.go:4899		0x45c047		7450			JE 0x45c099                                                                                                                                               │
    │   traceruntime.go:261	0x45c049		488b4c2420		MOVQ 0x20(SP), CX                                                                                                                              │
    │   traceruntime.go:261	0x45c04e		8b9130030000		MOVL 0x330(CX), DX                                                                                                                           │
    │   proc.go:4900		0x45c054		90			NOPL                                                                                                                                                        │
    │   traceruntime.go:261	0x45c055		85d2			TESTL DX, DX                                                                                                                                        │
    │   traceruntime.go:261	0x45c057		760a			JBE 0x45c063                                                                                                                                        │
    │   traceruntime.go:262	0x45c059		ffca			DECL DX                                                                                                                                             │
    │   traceruntime.go:262	0x45c05b		899130030000		MOVL DX, 0x330(CX)                                                                                                                           │
    │   traceruntime.go:262	0x45c061		eb0f			JMP 0x45c072                                                                                                                                        │
    │   traceruntime.go:264	0x45c063		90			NOPL                                                                                                                                                  │
    │   types.go:420		0x45c064		ba01000000		MOVL $0x1, DX                                                                                                                                        │
    │   types.go:420		0x45c069		f0480fc19100030000	LOCK XADDQ DX, 0x300(CX)                                                                                                                      │
    │   runtime1.go:637	0x45c072		8b9100010000		MOVL 0x100(CX), DX                                                                                                                               │
    │   runtime1.go:637	0x45c078		8d5aff			LEAL -0x1(DX), BX                                                                                                                                     │
    │   traceruntime.go:270	0x45c07b		90			NOPL                                                                                                                                                  │
    │   runtime1.go:637	0x45c07c		899900010000		MOVL BX, 0x100(CX)                                                                                                                               │
    │   runtime1.go:638	0x45c082		83fa01			CMPL DX, $0x1                                                                                                                                         │
    │   runtime1.go:638	0x45c085		7512			JNE 0x45c099                                                                                                                                            │
    │   runtime1.go:638	0x45c087		4180beb100000000	CMPB 0xb1(R14), $0x0                                                                                                                          │
    │   runtime1.go:638	0x45c08f		7408			JE 0x45c099                                                                                                                                             │
    │   runtime1.go:640	0x45c091		49c74610defaffff	MOVQ $-0x522, 0x10(R14)                                                                                                                       │
    │   proc.go:4902		0x45c099		b801000000		MOVL $0x1, AX                                                                                                                                        │
    │   proc.go:4902		0x45c09e		4883c438		ADDQ $0x38, SP                                                                                                                                         │
    │   proc.go:4902		0x45c0a2		5d			POPQ BP                                                                                                                                                     │
    │   proc.go:4902		0x45c0a3		c3			RET                                                                                                                                                         │
    │   proc.go:4890		0x45c0a4		31c0			XORL AX, AX                                                                                                                                               │
    │   proc.go:4890		0x45c0a6		4883c438		ADDQ $0x38, SP                                                                                                                                         │
    │   proc.go:4890		0x45c0aa		5d			POPQ BP                                                                                                                                                     │
    │   proc.go:4890		0x45c0ab		c3			RET                                                                                                                                                         │
    

    Hopefully this is of some use.

  10. prattmic commented on Nov 12, 2025

    @prattmic
    MemberAuthor

    Thanks, that does seem useful. For completeness, where is 0x45d681? Is that in runtime.exitsyscall?

  11. modified the milestones: Go1.26, Go1.27 on Feb 10, 2026
  12. gopherbot commented on Aug 15, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/815820 mentions this issue: runtime/pprof: avoid panic for sigprofNonGoPC short stacks

  13. modified the milestones: Go1.27, Go1.28 on Aug 19, 2026
  14. added
    cgoIssues affecting runtime/cgo and cmd/go
    on Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.cgoIssues affecting runtime/cgo and cmd/gocompiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions