]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: record goroutine creation pc and display in traceback
authorRuss Cox <rsc@golang.org>
Wed, 2 Mar 2011 18:42:02 +0000 (13:42 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 2 Mar 2011 18:42:02 +0000 (13:42 -0500)
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

src/pkg/runtime/amd64/traceback.c
src/pkg/runtime/arm/traceback.c
src/pkg/runtime/mgc0.c
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 035dc560c5a8d088fd3fdf6193f59b0f325c917c..0f6733c364058fe5156f8e5cd454320842be5028 100644 (file)
@@ -182,6 +182,17 @@ gentraceback(byte *pc0, byte *sp, G *g, int32 skip, uintptr *pcbuf, int32 max)
                sp = fp;
                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;
 }
 
index ce0c287f3cb2520ed148db798f2b862adaebdb13..ad3096823e36bd661beee8230f13db969e9e998c 100644 (file)
@@ -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)
                        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;               
 }
 
index 1d382580fa5a4b0160494b1ef8ce83167d8395d5..7c175b308adc161ae429e9a35db95b179f8b4172 100644 (file)
@@ -585,7 +585,7 @@ runtime·gc(int32 force)
        if(fp != nil) {
                // kick off or wake up goroutine to run queued finalizers
                if(fing == nil)
-                       fing = runtime·newproc1((byte*)runfinq, nil, 0, 0);
+                       fing = runtime·newproc1((byte*)runfinq, nil, 0, 0, runtime·gc);
                else if(fingwait) {
                        fingwait = 0;
                        runtime·ready(fing);
index ba16f48bbc0a309b42d4ecd83ed566274e8e3f6f..db6072b5ce719bcaf54c99f5c13902c2d2548cbc 100644 (file)
@@ -884,11 +884,11 @@ runtime·newproc(int32 siz, byte* fn, ...)
                argp = (byte*)(&fn+2);  // skip caller's saved LR
        else
                argp = (byte*)(&fn+1);
-       runtime·newproc1(fn, argp, siz, 0);
+       runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz));
 }
 
 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;
        G *newg;
@@ -926,6 +926,7 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret)
        newg->sched.pc = (byte*)runtime·goexit;
        newg->sched.g = newg;
        newg->entry = fn;
+       newg->gopc = (uintptr)callerpc;
 
        runtime·sched.gcount++;
        runtime·goidgen++;
index 5db86a177123edda848a1a394401d18c6b03d2b7..85dca54f7dcec4439a7ae02972fea2818f6c1479 100644 (file)
@@ -202,6 +202,7 @@ struct      G
        uintptr sigcode0;
        uintptr sigcode1;
        uintptr sigpc;
+       uintptr gopc;   // pc of go statement that created this goroutine
 };
 struct M
 {
@@ -452,7 +453,7 @@ void        runtime·entersyscall(void);
 void   runtime·exitsyscall(void);
 void   runtime·startcgocallback(G*);
 void   runtime·endcgocallback(G*);
-G*     runtime·newproc1(byte*, byte*, int32, int32);
+G*     runtime·newproc1(byte*, byte*, int32, int32, void*);
 void   runtime·siginit(void);
 bool   runtime·sigsend(int32 sig);
 void   runtime·gettime(int64*, int32*);