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 "go-defer.h" 7 #include "go-panic.h" 8 9 // Code related to defer, panic and recover. 10 11 uint32 runtime_panicking; 12 static Lock paniclk; 13 14 // Run all deferred functions for the current goroutine. 15 static void rundefer(void)16rundefer(void) 17 { 18 G *g; 19 Defer *d; 20 21 g = runtime_g(); 22 while((d = g->defer) != nil) { 23 void (*pfn)(void*); 24 25 g->defer = d->__next; 26 pfn = d->__pfn; 27 d->__pfn = nil; 28 if (pfn != nil) 29 (*pfn)(d->__arg); 30 runtime_free(d); 31 } 32 } 33 34 void runtime_startpanic(void)35runtime_startpanic(void) 36 { 37 M *m; 38 39 m = runtime_m(); 40 if(m->dying) { 41 runtime_printf("panic during panic\n"); 42 runtime_exit(3); 43 } 44 m->dying = 1; 45 runtime_xadd(&runtime_panicking, 1); 46 runtime_lock(&paniclk); 47 } 48 49 void runtime_dopanic(int32 unused)50runtime_dopanic(int32 unused __attribute__ ((unused))) 51 { 52 G *g; 53 static bool didothers; 54 55 g = runtime_g(); 56 if(g->sig != 0) 57 runtime_printf("[signal %x code=%p addr=%p]\n", 58 g->sig, (void*)g->sigcode0, (void*)g->sigcode1); 59 60 if(runtime_gotraceback()){ 61 if(g != runtime_m()->g0) { 62 runtime_printf("\n"); 63 runtime_goroutineheader(g); 64 runtime_traceback(); 65 runtime_goroutinetrailer(g); 66 } 67 if(!didothers) { 68 didothers = true; 69 runtime_tracebackothers(g); 70 } 71 } 72 runtime_unlock(&paniclk); 73 if(runtime_xadd(&runtime_panicking, -1) != 0) { 74 // Some other m is panicking too. 75 // Let it print what it needs to print. 76 // Wait forever without chewing up cpu. 77 // It will exit when it's done. 78 static Lock deadlock; 79 runtime_lock(&deadlock); 80 runtime_lock(&deadlock); 81 } 82 83 runtime_exit(2); 84 } 85 86 void runtime_throw(const char * s)87runtime_throw(const char *s) 88 { 89 M *mp; 90 91 mp = runtime_m(); 92 if(mp->throwing == 0) 93 mp->throwing = 1; 94 runtime_startpanic(); 95 runtime_printf("fatal error: %s\n", s); 96 runtime_dopanic(0); 97 *(int32*)0 = 0; // not reached 98 runtime_exit(1); // even more not reached 99 } 100 101 void runtime_panicstring(const char * s)102runtime_panicstring(const char *s) 103 { 104 Eface err; 105 106 if(runtime_m()->gcing) { 107 runtime_printf("panic: %s\n", s); 108 runtime_throw("panic during gc"); 109 } 110 runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err); 111 runtime_panic(err); 112 } 113 114 void runtime_Goexit (void) __asm__ (GOSYM_PREFIX "runtime.Goexit"); 115 116 void runtime_Goexit(void)117runtime_Goexit(void) 118 { 119 rundefer(); 120 runtime_goexit(); 121 } 122