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.
runtime/pprof.appendLocsForStackasserts 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. Incgocallbackg, we clear this field afterexitsyscallreturns. 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 thiscgocallbackcontext could trigger thisappendLocsForStackpanic.I do not know if any code reachable in this window actually has more than 2 inlined frames. Only 2 frames is insufficient, as
appendLocsForStackwouldn't actually care that the second frame isruntime._ExternalCodeinstead of the proper frame.One potential fix is to attempt to do inline expansion in
sigprofNonGoPCin case it actually is a Go PC.