github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/panic.c (about) 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 "arch_GOARCH.h" 7 #include "stack.h" 8 #include "malloc.h" 9 #include "../../cmd/ld/textflag.h" 10 11 // Code related to defer, panic and recover. 12 13 uint32 runtime·panicking; 14 static Lock paniclk; 15 16 enum 17 { 18 DeferChunkSize = 2048 19 }; 20 21 // Allocate a Defer, usually as part of the larger frame of deferred functions. 22 // Each defer must be released with both popdefer and freedefer. 23 static Defer* 24 newdefer(int32 siz) 25 { 26 int32 total; 27 DeferChunk *c; 28 Defer *d; 29 30 c = g->dchunk; 31 total = sizeof(*d) + ROUND(siz, sizeof(uintptr)) - sizeof(d->args); 32 if(c == nil || total > DeferChunkSize - c->off) { 33 if(total > DeferChunkSize / 2) { 34 // Not worth putting in any chunk. 35 // Allocate a separate block. 36 d = runtime·malloc(total); 37 d->siz = siz; 38 d->special = 1; 39 d->free = 1; 40 d->link = g->defer; 41 g->defer = d; 42 return d; 43 } 44 45 // Cannot fit in current chunk. 46 // Switch to next chunk, allocating if necessary. 47 c = g->dchunknext; 48 if(c == nil) 49 c = runtime·malloc(DeferChunkSize); 50 c->prev = g->dchunk; 51 c->off = sizeof(*c); 52 g->dchunk = c; 53 g->dchunknext = nil; 54 } 55 56 d = (Defer*)((byte*)c + c->off); 57 c->off += total; 58 d->siz = siz; 59 d->special = 0; 60 d->free = 0; 61 d->link = g->defer; 62 g->defer = d; 63 return d; 64 } 65 66 // Pop the current defer from the defer stack. 67 // Its contents are still valid until the goroutine begins executing again. 68 // In particular it is safe to call reflect.call(d->fn, d->argp, d->siz) after 69 // popdefer returns. 70 static void 71 popdefer(void) 72 { 73 Defer *d; 74 DeferChunk *c; 75 int32 total; 76 77 d = g->defer; 78 if(d == nil) 79 runtime·throw("runtime: popdefer nil"); 80 g->defer = d->link; 81 if(d->special) { 82 // Nothing else to do. 83 return; 84 } 85 total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args); 86 c = g->dchunk; 87 if(c == nil || (byte*)d+total != (byte*)c+c->off) 88 runtime·throw("runtime: popdefer phase error"); 89 c->off -= total; 90 if(c->off == sizeof(*c)) { 91 // Chunk now empty, so pop from stack. 92 // Save in dchunknext both to help with pingponging between frames 93 // and to make sure d is still valid on return. 94 if(g->dchunknext != nil) 95 runtime·free(g->dchunknext); 96 g->dchunknext = c; 97 g->dchunk = c->prev; 98 } 99 } 100 101 // Free the given defer. 102 // For defers in the per-goroutine chunk this just clears the saved arguments. 103 // For large defers allocated on the heap, this frees them. 104 // The defer cannot be used after this call. 105 static void 106 freedefer(Defer *d) 107 { 108 int32 total; 109 110 if(d->special) { 111 if(d->free) 112 runtime·free(d); 113 } else { 114 // Wipe out any possible pointers in argp/pc/fn/args. 115 total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args); 116 runtime·memclr((byte*)d, total); 117 } 118 } 119 120 // Create a new deferred function fn with siz bytes of arguments. 121 // The compiler turns a defer statement into a call to this. 122 // Cannot split the stack because it assumes that the arguments 123 // are available sequentially after &fn; they would not be 124 // copied if a stack split occurred. It's OK for this to call 125 // functions that split the stack. 126 #pragma textflag NOSPLIT 127 uintptr 128 runtime·deferproc(int32 siz, FuncVal *fn, ...) 129 { 130 Defer *d; 131 132 d = newdefer(siz); 133 d->fn = fn; 134 d->pc = runtime·getcallerpc(&siz); 135 if(thechar == '5') 136 d->argp = (byte*)(&fn+2); // skip caller's saved link register 137 else 138 d->argp = (byte*)(&fn+1); 139 runtime·memmove(d->args, d->argp, d->siz); 140 141 // deferproc returns 0 normally. 142 // a deferred func that stops a panic 143 // makes the deferproc return 1. 144 // the code the compiler generates always 145 // checks the return value and jumps to the 146 // end of the function if deferproc returns != 0. 147 return 0; 148 } 149 150 // Run a deferred function if there is one. 151 // The compiler inserts a call to this at the end of any 152 // function which calls defer. 153 // If there is a deferred function, this will call runtime·jmpdefer, 154 // which will jump to the deferred function such that it appears 155 // to have been called by the caller of deferreturn at the point 156 // just before deferreturn was called. The effect is that deferreturn 157 // is called again and again until there are no more deferred functions. 158 // Cannot split the stack because we reuse the caller's frame to 159 // call the deferred function. 160 // 161 // The ... in the prototype keeps the compiler from declaring 162 // an argument frame size. deferreturn is a very special function, 163 // and if the runtime ever asks for its frame size, that means 164 // the traceback routines are probably broken. 165 #pragma textflag NOSPLIT 166 void 167 runtime·deferreturn(uintptr arg0, ...) 168 { 169 Defer *d; 170 byte *argp; 171 FuncVal *fn; 172 173 d = g->defer; 174 if(d == nil) 175 return; 176 argp = (byte*)&arg0; 177 if(d->argp != argp) 178 return; 179 180 // Moving arguments around. 181 // Do not allow preemption here, because the garbage collector 182 // won't know the form of the arguments until the jmpdefer can 183 // flip the PC over to fn. 184 m->locks++; 185 runtime·memmove(argp, d->args, d->siz); 186 fn = d->fn; 187 popdefer(); 188 freedefer(d); 189 m->locks--; 190 if(m->locks == 0 && g->preempt) 191 g->stackguard0 = StackPreempt; 192 runtime·jmpdefer(fn, argp); 193 } 194 195 // Run all deferred functions for the current goroutine. 196 static void 197 rundefer(void) 198 { 199 Defer *d; 200 201 while((d = g->defer) != nil) { 202 popdefer(); 203 reflect·call(d->fn, (byte*)d->args, d->siz); 204 freedefer(d); 205 } 206 } 207 208 // Print all currently active panics. Used when crashing. 209 static void 210 printpanics(Panic *p) 211 { 212 if(p->link) { 213 printpanics(p->link); 214 runtime·printf("\t"); 215 } 216 runtime·printf("panic: "); 217 runtime·printany(p->arg); 218 if(p->recovered) 219 runtime·printf(" [recovered]"); 220 runtime·printf("\n"); 221 } 222 223 static void recovery(G*); 224 225 // The implementation of the predeclared function panic. 226 void 227 runtime·panic(Eface e) 228 { 229 Defer *d; 230 Panic *p; 231 void *pc, *argp; 232 233 p = runtime·mal(sizeof *p); 234 p->arg = e; 235 p->link = g->panic; 236 p->stackbase = g->stackbase; 237 g->panic = p; 238 239 for(;;) { 240 d = g->defer; 241 if(d == nil) 242 break; 243 // take defer off list in case of recursive panic 244 popdefer(); 245 g->ispanic = true; // rock for newstack, where reflect.newstackcall ends up 246 argp = d->argp; 247 pc = d->pc; 248 runtime·newstackcall(d->fn, (byte*)d->args, d->siz); 249 freedefer(d); 250 if(p->recovered) { 251 g->panic = p->link; 252 if(g->panic == nil) // must be done with signal 253 g->sig = 0; 254 runtime·free(p); 255 // Pass information about recovering frame to recovery. 256 g->sigcode0 = (uintptr)argp; 257 g->sigcode1 = (uintptr)pc; 258 runtime·mcall(recovery); 259 runtime·throw("recovery failed"); // mcall should not return 260 } 261 } 262 263 // ran out of deferred calls - old-school panic now 264 runtime·startpanic(); 265 printpanics(g->panic); 266 runtime·dopanic(0); 267 } 268 269 // Unwind the stack after a deferred function calls recover 270 // after a panic. Then arrange to continue running as though 271 // the caller of the deferred function returned normally. 272 static void 273 recovery(G *gp) 274 { 275 void *argp; 276 uintptr pc; 277 278 // Info about defer passed in G struct. 279 argp = (void*)gp->sigcode0; 280 pc = (uintptr)gp->sigcode1; 281 282 // Unwind to the stack frame with d's arguments in it. 283 runtime·unwindstack(gp, argp); 284 285 // Make the deferproc for this d return again, 286 // this time returning 1. The calling function will 287 // jump to the standard return epilogue. 288 // The -2*sizeof(uintptr) makes up for the 289 // two extra words that are on the stack at 290 // each call to deferproc. 291 // (The pc we're returning to does pop pop 292 // before it tests the return value.) 293 // On the arm there are 2 saved LRs mixed in too. 294 if(thechar == '5') 295 gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr); 296 else 297 gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr); 298 gp->sched.pc = pc; 299 gp->sched.lr = 0; 300 gp->sched.ret = 1; 301 runtime·gogo(&gp->sched); 302 } 303 304 // Free stack frames until we hit the last one 305 // or until we find the one that contains the sp. 306 void 307 runtime·unwindstack(G *gp, byte *sp) 308 { 309 Stktop *top; 310 byte *stk; 311 312 // Must be called from a different goroutine, usually m->g0. 313 if(g == gp) 314 runtime·throw("unwindstack on self"); 315 316 while((top = (Stktop*)gp->stackbase) != 0 && top->stackbase != 0) { 317 stk = (byte*)gp->stackguard - StackGuard; 318 if(stk <= sp && sp < (byte*)gp->stackbase) 319 break; 320 gp->stackbase = top->stackbase; 321 gp->stackguard = top->stackguard; 322 gp->stackguard0 = gp->stackguard; 323 if(top->free != 0) { 324 gp->stacksize -= top->free; 325 runtime·stackfree(stk, top->free); 326 } 327 } 328 329 if(sp != nil && (sp < (byte*)gp->stackguard - StackGuard || (byte*)gp->stackbase < sp)) { 330 runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackguard - StackGuard, gp->stackbase); 331 runtime·throw("bad unwindstack"); 332 } 333 } 334 335 // The implementation of the predeclared function recover. 336 // Cannot split the stack because it needs to reliably 337 // find the stack segment of its caller. 338 #pragma textflag NOSPLIT 339 void 340 runtime·recover(byte *argp, Eface ret) 341 { 342 Panic *p; 343 Stktop *top; 344 345 // Must be an unrecovered panic in progress. 346 // Must be on a stack segment created for a deferred call during a panic. 347 // Must be at the top of that segment, meaning the deferred call itself 348 // and not something it called. The top frame in the segment will have 349 // argument pointer argp == top - top->argsize. 350 // The subtraction of g->panicwrap allows wrapper functions that 351 // do not count as official calls to adjust what we consider the top frame 352 // while they are active on the stack. The linker emits adjustments of 353 // g->panicwrap in the prologue and epilogue of functions marked as wrappers. 354 top = (Stktop*)g->stackbase; 355 p = g->panic; 356 if(p != nil && !p->recovered && top->panic && argp == (byte*)top - top->argsize - g->panicwrap) { 357 p->recovered = 1; 358 ret = p->arg; 359 } else { 360 ret.type = nil; 361 ret.data = nil; 362 } 363 FLUSH(&ret); 364 } 365 366 void 367 runtime·startpanic(void) 368 { 369 if(runtime·mheap.cachealloc.size == 0) { // very early 370 runtime·printf("runtime: panic before malloc heap initialized\n"); 371 m->mallocing = 1; // tell rest of panic not to try to malloc 372 } else if(m->mcache == nil) // can happen if called from signal handler or throw 373 m->mcache = runtime·allocmcache(); 374 if(m->dying) { 375 runtime·printf("panic during panic\n"); 376 runtime·exit(3); 377 } 378 m->dying = 1; 379 if(g != nil) 380 g->writebuf = nil; 381 runtime·xadd(&runtime·panicking, 1); 382 runtime·lock(&paniclk); 383 if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0) 384 runtime·schedtrace(true); 385 runtime·freezetheworld(); 386 } 387 388 void 389 runtime·dopanic(int32 unused) 390 { 391 static bool didothers; 392 bool crash; 393 int32 t; 394 395 if(g->sig != 0) 396 runtime·printf("[signal %x code=%p addr=%p pc=%p]\n", 397 g->sig, g->sigcode0, g->sigcode1, g->sigpc); 398 399 if((t = runtime·gotraceback(&crash)) > 0){ 400 if(g != m->g0) { 401 runtime·printf("\n"); 402 runtime·goroutineheader(g); 403 runtime·traceback((uintptr)runtime·getcallerpc(&unused), (uintptr)runtime·getcallersp(&unused), 0, g); 404 } else if(t >= 2 || m->throwing > 0) { 405 runtime·printf("\nruntime stack:\n"); 406 runtime·traceback((uintptr)runtime·getcallerpc(&unused), (uintptr)runtime·getcallersp(&unused), 0, g); 407 } 408 if(!didothers) { 409 didothers = true; 410 runtime·tracebackothers(g); 411 } 412 } 413 runtime·unlock(&paniclk); 414 if(runtime·xadd(&runtime·panicking, -1) != 0) { 415 // Some other m is panicking too. 416 // Let it print what it needs to print. 417 // Wait forever without chewing up cpu. 418 // It will exit when it's done. 419 static Lock deadlock; 420 runtime·lock(&deadlock); 421 runtime·lock(&deadlock); 422 } 423 424 if(crash) 425 runtime·crash(); 426 427 runtime·exit(2); 428 } 429 430 void 431 runtime·panicindex(void) 432 { 433 runtime·panicstring("index out of range"); 434 } 435 436 void 437 runtime·panicslice(void) 438 { 439 runtime·panicstring("slice bounds out of range"); 440 } 441 442 void 443 runtime·throwreturn(void) 444 { 445 // can only happen if compiler is broken 446 runtime·throw("no return at end of a typed function - compiler is broken"); 447 } 448 449 void 450 runtime·throwinit(void) 451 { 452 // can only happen with linker skew 453 runtime·throw("recursive call during initialization - linker skew"); 454 } 455 456 void 457 runtime·throw(int8 *s) 458 { 459 if(m->throwing == 0) 460 m->throwing = 1; 461 runtime·startpanic(); 462 runtime·printf("fatal error: %s\n", s); 463 runtime·dopanic(0); 464 *(int32*)0 = 0; // not reached 465 runtime·exit(1); // even more not reached 466 } 467 468 void 469 runtime·panicstring(int8 *s) 470 { 471 Eface err; 472 473 if(m->mallocing) { 474 runtime·printf("panic: %s\n", s); 475 runtime·throw("panic during malloc"); 476 } 477 if(m->gcing) { 478 runtime·printf("panic: %s\n", s); 479 runtime·throw("panic during gc"); 480 } 481 runtime·newErrorCString(s, &err); 482 runtime·panic(err); 483 } 484 485 void 486 runtime·Goexit(void) 487 { 488 rundefer(); 489 runtime·goexit(); 490 }