1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "runtime.h" 6 #include "malloc.h" 7 #include "go-defer.h" 8 #include "go-panic.h" 9 10 // Code related to defer, panic and recover. 11 12 uint32 runtime_panicking; 13 static Lock paniclk; 14 15 // Run all deferred functions for the current goroutine. 16 static void rundefer(void)17rundefer(void) 18 { 19 G *g; 20 Defer *d; 21 22 g = runtime_g(); 23 while((d = g->defer) != nil) { 24 void (*pfn)(void*); 25 26 g->defer = d->__next; 27 pfn = d->__pfn; 28 d->__pfn = nil; 29 if (pfn != nil) 30 (*pfn)(d->__arg); 31 runtime_free(d); 32 } 33 } 34 35 void runtime_startpanic(void)36runtime_startpanic(void) 37 { 38 M *m; 39 40 m = runtime_m(); 41 if(runtime_mheap == 0 || runtime_mheap->cachealloc.size == 0) { // very early 42 runtime_printf("runtime: panic before malloc heap initialized\n"); 43 m->mallocing = 1; // tell rest of panic not to try to malloc 44 } else if(m->mcache == nil) // can happen if called from signal handler or throw 45 m->mcache = runtime_allocmcache(); 46 if(m->dying) { 47 runtime_printf("panic during panic\n"); 48 runtime_exit(3); 49 } 50 m->dying = 1; 51 runtime_xadd(&runtime_panicking, 1); 52 runtime_lock(&paniclk); 53 } 54 55 void runtime_dopanic(int32 unused)56runtime_dopanic(int32 unused __attribute__ ((unused))) 57 { 58 G *g; 59 static bool didothers; 60 bool crash; 61 62 g = runtime_g(); 63 if(g->sig != 0) 64 runtime_printf("[signal %x code=%p addr=%p]\n", 65 g->sig, (void*)g->sigcode0, (void*)g->sigcode1); 66 67 if(runtime_gotraceback(&crash)){ 68 if(g != runtime_m()->g0) { 69 runtime_printf("\n"); 70 runtime_goroutineheader(g); 71 runtime_traceback(); 72 runtime_goroutinetrailer(g); 73 } 74 if(!didothers) { 75 didothers = true; 76 runtime_tracebackothers(g); 77 } 78 } 79 runtime_unlock(&paniclk); 80 if(runtime_xadd(&runtime_panicking, -1) != 0) { 81 // Some other m is panicking too. 82 // Let it print what it needs to print. 83 // Wait forever without chewing up cpu. 84 // It will exit when it's done. 85 static Lock deadlock; 86 runtime_lock(&deadlock); 87 runtime_lock(&deadlock); 88 } 89 90 if(crash) 91 runtime_crash(); 92 93 runtime_exit(2); 94 } 95 96 void runtime_throw(const char * s)97runtime_throw(const char *s) 98 { 99 M *mp; 100 101 mp = runtime_m(); 102 if(mp->throwing == 0) 103 mp->throwing = 1; 104 runtime_startpanic(); 105 runtime_printf("fatal error: %s\n", s); 106 runtime_dopanic(0); 107 *(int32*)0 = 0; // not reached 108 runtime_exit(1); // even more not reached 109 } 110 111 void runtime_panicstring(const char * s)112runtime_panicstring(const char *s) 113 { 114 Eface err; 115 116 if(runtime_m()->gcing) { 117 runtime_printf("panic: %s\n", s); 118 runtime_throw("panic during gc"); 119 } 120 runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err); 121 runtime_panic(err); 122 } 123 124 void runtime_Goexit (void) __asm__ (GOSYM_PREFIX "runtime.Goexit"); 125 126 void runtime_Goexit(void)127runtime_Goexit(void) 128 { 129 rundefer(); 130 runtime_goexit(); 131 } 132