]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: dump the full stack of a throwing goroutine
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 29 Jan 2013 10:57:11 +0000 (14:57 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 29 Jan 2013 10:57:11 +0000 (14:57 +0400)
Useful for debugging of runtime bugs.
+ Do not print "stack segment boundary" unless GOTRACEBACK>1.
+ Do not traceback system goroutines unless GOTRACEBACK>1.

R=rsc, minux.ma
CC=golang-dev
https://golang.org/cl/7098050

src/pkg/runtime/panic.c
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h
src/pkg/runtime/symtab.c
src/pkg/runtime/time.goc
src/pkg/runtime/traceback_arm.c
src/pkg/runtime/traceback_x86.c

index c96007dd16accffef578fee393e227c00096aae3..a0651e4ad55e8d4d0804ddc39d8adbcbfe003986 100644 (file)
@@ -454,6 +454,8 @@ runtime·throwinit(void)
 void
 runtime·throw(int8 *s)
 {
+       if(m->throwing == 0)
+               m->throwing = 1;
        runtime·startpanic();
        runtime·printf("fatal error: %s\n", s);
        runtime·dopanic(0);
index cd66bcecdb7a1f392c90b38ce13c0adb869ba46c..9b143b92f3e457142f421dcb4bc87824f1d941ac 100644 (file)
@@ -242,6 +242,7 @@ runtime·main(void)
        setmcpumax(runtime·gomaxprocs);
        runtime·sched.init = true;
        scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·main);
+       scvg->issystem = true;
        main·init();
        runtime·sched.init = false;
        if(!runtime·sched.lockmain)
@@ -325,10 +326,14 @@ void
 runtime·tracebackothers(G *me)
 {
        G *gp;
+       int32 traceback;
 
+       traceback = runtime·gotraceback();
        for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
                if(gp == me || gp->status == Gdead)
                        continue;
+               if(gp->issystem && traceback < 2)
+                       continue;
                runtime·printf("\n");
                runtime·goroutineheader(gp);
                runtime·traceback(gp->sched.pc, (byte*)gp->sched.sp, 0, gp);
@@ -624,6 +629,7 @@ top:
        if((scvg == nil && runtime·sched.grunning == 0) ||
           (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
            (scvg->status == Grunning || scvg->status == Gsyscall))) {
+               m->throwing = -1;  // do not dump full stacks
                runtime·throw("all goroutines are asleep - deadlock!");
        }
 
index e21c276e179e854278d464c25b73962054c6601b..22aead792ccb724400540dea689691216bf601ae 100644 (file)
@@ -219,6 +219,7 @@ struct      G
        G*      schedlink;
        bool    readyonstop;
        bool    ispanic;
+       bool    issystem;
        int8    raceignore; // ignore race detection events
        M*      m;              // for debuggers, but offset not hard-coded
        M*      lockedm;
@@ -252,6 +253,7 @@ struct      M
        G*      curg;           // current running goroutine
        int32   id;
        int32   mallocing;
+       int32   throwing;
        int32   gcing;
        int32   locks;
        int32   nomemprof;
@@ -865,7 +867,7 @@ Hmap*       runtime·makemap_c(MapType*, int64);
 Hchan* runtime·makechan_c(ChanType*, int64);
 void   runtime·chansend(ChanType*, Hchan*, byte*, bool*, void*);
 void   runtime·chanrecv(ChanType*, Hchan*, byte*, bool*, bool*);
-bool   runtime·showframe(Func*);
+bool   runtime·showframe(Func*, bool);
 
 void   runtime·ifaceE2I(InterfaceType*, Eface, Iface*);
 
index 5df9fd2d3d0614a2d9efb527fc949b15728578da..a8679b1069659d849390cff8604a99f70bb5c2c8 100644 (file)
@@ -559,11 +559,13 @@ contains(String s, int8 *p)
 }
 
 bool
-runtime·showframe(Func *f)
+runtime·showframe(Func *f, bool current)
 {
        static int32 traceback = -1;
 
+       if(current && m->throwing > 0)
+               return 1;
        if(traceback < 0)
                traceback = runtime·gotraceback();
-       return traceback > 1 || contains(f->name, ".") && !hasprefix(f->name, "runtime.");
+       return traceback > 1 || f != nil && contains(f->name, ".") && !hasprefix(f->name, "runtime.");
 }
index 57a49ee58c996367a622f6be9c1ebd6da03c07a8..e41df2c572b5083360be6d7cab3207a49846af09 100644 (file)
@@ -108,8 +108,10 @@ addtimer(Timer *t)
                        runtime·ready(timers.timerproc);
                }
        }
-       if(timers.timerproc == nil)
+       if(timers.timerproc == nil) {
                timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0, addtimer);
+               timers.timerproc->issystem = true;
+       }
 }
 
 // Delete timer t from the heap.
index e67ccd415324fee970fa3e9b77e1d8182acfb190..da7ab570ca2c0c7db4dbb02cc845ab5f8be0cc7b 100644 (file)
@@ -25,7 +25,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
        bool waspanic;
        Stktop *stk;
        Func *f;
-       
+
        pc = (uintptr)pc0;
        lr = (uintptr)lr0;
        fp = nil;
@@ -60,7 +60,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        sp = (byte*)stk->gobuf.sp;
                        lr = 0;
                        fp = nil;
-                       if(pcbuf == nil)
+                       if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
                                runtime·printf("----- stack segment boundary -----\n");
                        stk = (Stktop*)stk->stackbase;
                        continue;
@@ -118,7 +118,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                else if(pcbuf != nil)
                        pcbuf[n++] = pc;
                else {
-                       if(runtime·showframe(f)) {
+                       if(runtime·showframe(f, gp == m->curg)) {
                                // Print during crash.
                                //      main(0x1, 0x2, 0x3)
                                //              /home/rsc/go/src/runtime/x.go:23 +0xf
@@ -184,7 +184,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        sp += 12;
        }
        
-       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && gp->goid != 1) {
+       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+                       && runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
                runtime·printf("created by %S\n", f->name);
                tracepc = pc;   // back up to CALL instruction for funcline.
                if(n > 0 && pc > f->entry)
index 45475560968c83aba3de3a4f71ad76c013e6178b..e235757b0f5c831df425e65f99aaca6908012e0f 100644 (file)
@@ -77,7 +77,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        sp = (byte*)stk->gobuf.sp;
                        lr = 0;
                        fp = nil;
-                       if(pcbuf == nil)
+                       if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
                                runtime·printf("----- stack segment boundary -----\n");
                        stk = (Stktop*)stk->stackbase;
                        continue;
@@ -126,7 +126,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                else if(pcbuf != nil)
                        pcbuf[n++] = pc;
                else {
-                       if(runtime·showframe(f)) {
+                       if(runtime·showframe(f, gp == m->curg)) {
                                // Print during crash.
                                //      main(0x1, 0x2, 0x3)
                                //              /home/rsc/go/src/runtime/x.go:23 +0xf
@@ -196,7 +196,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
        }
        
        // Show what created goroutine, except main goroutine (goid 1).
-       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && gp->goid != 1) {
+       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+                       && runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
                runtime·printf("created by %S\n", f->name);
                tracepc = pc;   // back up to CALL instruction for funcline.
                if(n > 0 && pc > f->entry)