// The implementation of the predeclared function panic. void runtime·panic(Eface e) { Defer *d; Panic *p; void *pc, *argp; p = runtime·mal(sizeof *p); p->arg = e; p->link = g->panic; p->stackbase = g->stackbase; g->panic = p; for(;;) { d = g->defer; if(d == nil) break; // take defer off list in case of recursive panic g->defer = d->link; g->ispanic = true; // rock for newstack, where reflect.newstackcall ends up argp = d->argp; pc = d->pc; runtime·newstackcall(d->fn, (byte*)d->args, d->siz); freedefer(d); if(p->recovered) { g->panic = p->link; if(g->panic == nil) // must be done with signal g->sig = 0; runtime·free(p); // Pass information about recovering frame to recovery. g->sigcode0 = (uintptr)argp; g->sigcode1 = (uintptr)pc; runtime·mcall(recovery); runtime·throw("recovery failed"); // mcall should not return } } // ran out of deferred calls - old-school panic now runtime·startpanic(); printpanics(g->panic); runtime·dopanic(0); }
void runtime·cgocallbackg1(void) { CallbackArgs *cb; Defer d; if(m->needextram) { m->needextram = 0; runtime·newextram(); } // Add entry to defer stack in case of panic. d.fn = &unwindmf; d.siz = 0; d.link = g->defer; d.argp = (void*)-1; // unused because unwindm never recovers d.special = true; d.free = false; g->defer = &d; if(raceenabled && !m->racecall) runtime·raceacquire(&cgosync); // Invoke callback. cb = CBARGS; runtime·newstackcall(cb->fn, cb->arg, cb->argsize); if(raceenabled && !m->racecall) runtime·racereleasemerge(&cgosync); // Pop defer. // Do not unwind m->g0->sched.sp. // Our caller, cgocallback, will do that. if(g->defer != &d || d.fn != &unwindmf) runtime·throw("runtime: bad defer entry in cgocallback"); g->defer = d.link; }