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.
9 // Code related to defer, panic and recover.
11 uint32 runtime_panicking
;
14 // Allocate a Defer, usually using per-P pool.
15 // Each defer must be released with freedefer.
23 p
= (P
*)runtime_m()->p
;
26 p
->deferpool
= d
->next
;
29 d
= runtime_malloc(sizeof(Defer
));
34 // Free the given defer.
35 // The defer cannot be used after this call.
37 runtime_freedefer(Defer
*d
)
43 p
= (P
*)runtime_m()->p
;
44 d
->next
= p
->deferpool
;
46 // No need to wipe out pointers in argp/pc/fn/args,
47 // because we empty the pool before GC.
50 // Run all deferred functions for the current goroutine.
51 // This is noinline for go_can_recover.
52 static void __go_rundefer (void) __attribute__ ((noinline
));
60 while((d
= g
->_defer
) != nil
) {
64 pfn
= (void (*) (void *))d
->pfn
;
73 runtime_startpanic(void)
78 if(runtime_mheap
.cachealloc
.size
== 0) { // very early
79 runtime_printf("runtime: panic before malloc heap initialized\n");
80 m
->mallocing
= 1; // tell rest of panic not to try to malloc
81 } else if(m
->mcache
== nil
) // can happen if called from signal handler or throw
82 m
->mcache
= runtime_allocmcache();
86 if(runtime_g() != nil
)
87 runtime_g()->writebuf
= nil
;
88 runtime_xadd(&runtime_panicking
, 1);
89 runtime_lock(&paniclk
);
90 if(runtime_debug
.schedtrace
> 0 || runtime_debug
.scheddetail
> 0)
91 runtime_schedtrace(true);
92 runtime_freezetheworld();
95 // Something failed while panicing, probably the print of the
96 // argument to panic(). Just print a stack trace and exit.
98 runtime_printf("panic during panic\n");
102 // This is a genuine bug in the runtime, we couldn't even
103 // print the stack trace successfully.
105 runtime_printf("stack trace unavailable\n");
108 // Can't even print! Just exit.
114 runtime_dopanic(int32 unused
__attribute__ ((unused
)))
117 static bool didothers
;
123 runtime_printf("[signal %x code=%p addr=%p]\n",
124 g
->sig
, (void*)g
->sigcode0
, (void*)g
->sigcode1
);
126 if((t
= runtime_gotraceback(&crash
)) > 0){
127 if(g
!= runtime_m()->g0
) {
128 runtime_printf("\n");
129 runtime_goroutineheader(g
);
131 runtime_printcreatedby(g
);
132 } else if(t
>= 2 || runtime_m()->throwing
> 0) {
133 runtime_printf("\nruntime stack:\n");
138 runtime_tracebackothers(g
);
141 runtime_unlock(&paniclk
);
142 if(runtime_xadd(&runtime_panicking
, -1) != 0) {
143 // Some other m is panicking too.
144 // Let it print what it needs to print.
145 // Wait forever without chewing up cpu.
146 // It will exit when it's done.
147 static Lock deadlock
;
148 runtime_lock(&deadlock
);
149 runtime_lock(&deadlock
);
159 runtime_canpanic(G
*gp
)
164 USED(&g
); // don't use global g, it points to gsignal
166 // Is it okay for gp to panic instead of crashing the program?
167 // Yes, as long as it is running Go code, not runtime code,
168 // and not stuck in a system call.
169 if(gp
== nil
|| gp
!= m
->curg
)
171 if(m
->locks
-m
->softfloat
!= 0 || m
->mallocing
!= 0 || m
->throwing
!= 0 || m
->gcing
!= 0 || m
->dying
!= 0)
173 if(gp
->atomicstatus
!= _Grunning
)
176 if(m
->libcallsp
!= 0)
183 runtime_throw(const char *s
)
188 if(mp
->throwing
== 0)
190 runtime_startpanic();
191 runtime_printf("fatal error: %s\n", s
);
193 *(int32
*)0 = 0; // not reached
194 runtime_exit(1); // even more not reached
197 void throw(String
) __asm__ (GOSYM_PREFIX
"runtime.throw");
204 if(mp
->throwing
== 0)
206 runtime_startpanic();
207 runtime_printf("fatal error: %S\n", s
);
209 *(int32
*)0 = 0; // not reached
210 runtime_exit(1); // even more not reached
214 runtime_panicstring(const char *s
)
218 if(runtime_m()->mallocing
) {
219 runtime_printf("panic: %s\n", s
);
220 runtime_throw("panic during malloc");
222 if(runtime_m()->gcing
) {
223 runtime_printf("panic: %s\n", s
);
224 runtime_throw("panic during gc");
226 if(runtime_m()->locks
) {
227 runtime_printf("panic: %s\n", s
);
228 runtime_throw("panic holding locks");
230 runtime_newErrorCString(s
, &err
);
234 void runtime_Goexit (void) __asm__ (GOSYM_PREFIX
"runtime.Goexit");
244 runtime_panicdivide(void)
246 runtime_panicstring("integer divide by zero");