Commit 324cc3d0 authored by Russ Cox's avatar Russ Cox

runtime: record goroutine creation pc and display in traceback

package main

func main() {
        go func() { *(*int)(nil) = 0 }()
        select{}
}

panic: runtime error: invalid memory address or nil pointer dereference

[signal 0xb code=0x1 addr=0x0 pc=0x1c96]

runtime.panic+0xac /Users/rsc/g/go/src/pkg/runtime/proc.c:1083
        runtime.panic(0x11bf0, 0xf8400011f0)
runtime.panicstring+0xa3 /Users/rsc/g/go/src/pkg/runtime/runtime.c:116
        runtime.panicstring(0x29a57, 0x0)
runtime.sigpanic+0x144 /Users/rsc/g/go/src/pkg/runtime/darwin/thread.c:470
        runtime.sigpanic()
main._func_001+0x16 /Users/rsc/g/go/src/pkg/runtime/x.go:188
        main._func_001()
runtime.goexit /Users/rsc/g/go/src/pkg/runtime/proc.c:150
        runtime.goexit()
----- goroutine created by -----
main.main+0x3d /Users/rsc/g/go/src/pkg/runtime/x.go:4

goroutine 1 [4]:
runtime.gosched+0x77 /Users/rsc/g/go/src/pkg/runtime/proc.c:598
        runtime.gosched()
runtime.block+0x27 /Users/rsc/g/go/src/pkg/runtime/chan.c:680
        runtime.block()
main.main+0x44 /Users/rsc/g/go/src/pkg/runtime/x.go:5
        main.main()
runtime.mainstart+0xf /Users/rsc/g/go/src/pkg/runtime/amd64/asm.s:77
        runtime.mainstart()
runtime.goexit /Users/rsc/g/go/src/pkg/runtime/proc.c:150
        runtime.goexit()
----- goroutine created by -----
_rt0_amd64+0x8e /Users/rsc/g/go/src/pkg/runtime/amd64/asm.s:64

Fixes #1563.

R=r
CC=golang-dev
https://golang.org/cl/4243046
parent 9733f96b
...@@ -182,6 +182,17 @@ gentraceback(byte *pc0, byte *sp, G *g, int32 skip, uintptr *pcbuf, int32 max) ...@@ -182,6 +182,17 @@ gentraceback(byte *pc0, byte *sp, G *g, int32 skip, uintptr *pcbuf, int32 max)
sp = fp; sp = fp;
fp = nil; fp = nil;
} }
if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil) {
runtime·printf("----- goroutine created by -----\n%S", f->name);
if(pc > f->entry)
runtime·printf("+%p", (uintptr)(pc - f->entry));
tracepc = pc; // back up to CALL instruction for funcline.
if(n > 0 && pc > f->entry)
tracepc--;
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
}
return n; return n;
} }
......
...@@ -175,6 +175,17 @@ gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, i ...@@ -175,6 +175,17 @@ gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, i
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc) if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
sp += 12; sp += 12;
} }
if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil) {
runtime·printf("----- goroutine created by -----\n%S", f->name);
if(pc > f->entry)
runtime·printf("+%p", (uintptr)(pc - f->entry));
tracepc = pc; // back up to CALL instruction for funcline.
if(n > 0 && pc > f->entry)
tracepc -= sizeof(uintptr);
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
}
return n; return n;
} }
......
...@@ -585,7 +585,7 @@ runtime·gc(int32 force) ...@@ -585,7 +585,7 @@ runtime·gc(int32 force)
if(fp != nil) { if(fp != nil) {
// kick off or wake up goroutine to run queued finalizers // kick off or wake up goroutine to run queued finalizers
if(fing == nil) if(fing == nil)
fing = runtime·newproc1((byte*)runfinq, nil, 0, 0); fing = runtime·newproc1((byte*)runfinq, nil, 0, 0, runtime·gc);
else if(fingwait) { else if(fingwait) {
fingwait = 0; fingwait = 0;
runtime·ready(fing); runtime·ready(fing);
......
...@@ -884,11 +884,11 @@ runtime·newproc(int32 siz, byte* fn, ...) ...@@ -884,11 +884,11 @@ runtime·newproc(int32 siz, byte* fn, ...)
argp = (byte*)(&fn+2); // skip caller's saved LR argp = (byte*)(&fn+2); // skip caller's saved LR
else else
argp = (byte*)(&fn+1); argp = (byte*)(&fn+1);
runtime·newproc1(fn, argp, siz, 0); runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz));
} }
G* G*
runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret) runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
{ {
byte *sp; byte *sp;
G *newg; G *newg;
...@@ -926,6 +926,7 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret) ...@@ -926,6 +926,7 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret)
newg->sched.pc = (byte*)runtime·goexit; newg->sched.pc = (byte*)runtime·goexit;
newg->sched.g = newg; newg->sched.g = newg;
newg->entry = fn; newg->entry = fn;
newg->gopc = (uintptr)callerpc;
runtime·sched.gcount++; runtime·sched.gcount++;
runtime·goidgen++; runtime·goidgen++;
......
...@@ -202,6 +202,7 @@ struct G ...@@ -202,6 +202,7 @@ struct G
uintptr sigcode0; uintptr sigcode0;
uintptr sigcode1; uintptr sigcode1;
uintptr sigpc; uintptr sigpc;
uintptr gopc; // pc of go statement that created this goroutine
}; };
struct M struct M
{ {
...@@ -452,7 +453,7 @@ void runtime·entersyscall(void); ...@@ -452,7 +453,7 @@ void runtime·entersyscall(void);
void runtime·exitsyscall(void); void runtime·exitsyscall(void);
void runtime·startcgocallback(G*); void runtime·startcgocallback(G*);
void runtime·endcgocallback(G*); void runtime·endcgocallback(G*);
G* runtime·newproc1(byte*, byte*, int32, int32); G* runtime·newproc1(byte*, byte*, int32, int32, void*);
void runtime·siginit(void); void runtime·siginit(void);
bool runtime·sigsend(int32 sig); bool runtime·sigsend(int32 sig);
void runtime·gettime(int64*, int32*); void runtime·gettime(int64*, int32*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment