コード例 #1
0
ファイル: runtime.c プロジェクト: krasin/go-deflate
void
runtime·dopanic(int32 unused)
{
	static bool didothers;

	if(g->sig != 0)
		runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
			g->sig, g->sigcode0, g->sigcode1, g->sigpc);

	if(runtime·gotraceback()){
		if(g != m->g0) {
			runtime·printf("\n");
			runtime·goroutineheader(g);
			runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g);
		}
		if(!didothers) {
			didothers = true;
			runtime·tracebackothers(g);
		}
	}
	runtime·unlock(&paniclk);
	if(runtime·xadd(&runtime·panicking, -1) != 0) {
		// Some other m is panicking too.
		// Let it print what it needs to print.
		// Wait forever without chewing up cpu.
		// It will exit when it's done.
		static Lock deadlock;
		runtime·lock(&deadlock);
		runtime·lock(&deadlock);
	}

	runtime·exit(2);
}
コード例 #2
0
void
runtime·tracebackothers(G *me)
{
	G *g;

	for(g = runtime·allg; g != nil; g = g->alllink) {
		if(g == me || g->status == Gdead)
			continue;
		runtime·printf("\n");
		runtime·goroutineheader(g);
		runtime·traceback(g->sched.pc, g->sched.sp, 0, g);
	}
}
コード例 #3
0
ファイル: proc.c プロジェクト: xorrbit/golang
void
runtime·tracebackothers(G *me)
{
    G *gp;
    int32 traceback;

    traceback = runtime·gotraceback();
    for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
        if(gp == me || gp->status == Gdead)
            continue;
        if(gp->issystem && traceback < 2)
            continue;
        runtime·printf("\n");
        runtime·goroutineheader(gp);
        runtime·traceback(gp->sched.pc, (byte*)gp->sched.sp, 0, gp);
    }
}
コード例 #4
0
ファイル: os_plan9_amd64.c プロジェクト: LEEWEN-DALIAN/golang
int32
runtime·sighandler(void *v, int8 *note, G *gp)
{
	uintptr *sp;
	SigTab *t;
	bool crash;
	Ureg *ureg;
	intgo len, n;
	int32 sig, flags;

	ureg = (Ureg*)v;

	// The kernel will never pass us a nil note or ureg so we probably
	// made a mistake somewhere in runtime·sigtramp.
	if(ureg == nil || note == nil) {
		runtime·printf("sighandler: ureg %p note %p\n", ureg, note);
		goto Throw;
	}

	// Check that the note is no more than ERRMAX bytes (including
	// the trailing NUL). We should never receive a longer note.
	len = runtime·findnull((byte*)note);
	if(len > ERRMAX-1) {
		runtime·printf("sighandler: note is longer than ERRMAX\n");
		goto Throw;
	}

	// See if the note matches one of the patterns in runtime·sigtab.
	// Notes that do not match any pattern can be handled at a higher
	// level by the program but will otherwise be ignored.
	flags = SigNotify;
	for(sig = 0; sig < nelem(runtime·sigtab); sig++) {
		t = &runtime·sigtab[sig];
		n = runtime·findnull((byte*)t->name);
		if(len < n)
			continue;
		if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) {
			flags = t->flags;
			break;
		}
	}

	if(flags & SigGoExit)
		runtime·exits(note+9); // Strip "go: exit " prefix.

	if(flags & SigPanic) {
		// Copy the error string from sigtramp's stack into m->notesig so
		// we can reliably access it from the panic routines.
		runtime·memmove(g->m->notesig, note, len+1);

		gp->sig = sig;
		gp->sigpc = ureg->ip;

		// Only push runtime·sigpanic if PC != 0.
		//
		// If PC == 0, probably panicked because of a call to a nil func.
		// Not pushing that onto SP will make the trace look like a call
		// to runtime·sigpanic instead. (Otherwise the trace will end at
		// runtime·sigpanic and we won't get to see who faulted).
		if(ureg->ip != 0) {
			sp = (uintptr*)ureg->sp;
			*--sp = ureg->ip;
			ureg->sp = (uint64)sp;
		}
		ureg->ip = (uintptr)runtime·sigpanic;
		return NCONT;
	}

	if(flags & SigNotify) {
		// TODO(ality): See if os/signal wants it.
		//if(runtime·sigsend(...))
		//	return NCONT;
	}
	if(flags & SigKill)
		goto Exit;
	if(!(flags & SigThrow))
		return NCONT;

Throw:
	g->m->throwing = 1;
	g->m->caughtsig = gp;
	runtime·startpanic();

	runtime·printf("%s\n", note);
	runtime·printf("PC=%X\n", ureg->ip);
	runtime·printf("\n");

	if(runtime·gotraceback(&crash)) {
		runtime·goroutineheader(gp);
		runtime·traceback(ureg->ip, ureg->sp, 0, gp);
		runtime·tracebackothers(gp);
		runtime·printf("\n");
		runtime·dumpregs(ureg);
	}
	
	if(crash)
		runtime·crash();

Exit:
	runtime·goexitsall(note);
	runtime·exits(note);
	return NDFLT; // not reached
}
コード例 #5
0
ファイル: signal_amd64x.c プロジェクト: LEEWEN-DALIAN/golang
void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
	uintptr *sp;
	SigTab *t;
	bool crash;

	if(sig == SIGPROF) {
		runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp, g->m);
		return;
	}

#ifdef GOOS_darwin
	// x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
	// The hardware delivers a different kind of fault for a malformed address
	// than it does for an attempt to access a valid but unmapped address.
	// OS X 10.9.2 mishandles the malformed address case, making it look like
	// a user-generated signal (like someone ran kill -SEGV ourpid).
	// We pass user-generated signals to os/signal, or else ignore them.
	// Doing that here - and returning to the faulting code - results in an
	// infinite loop. It appears the best we can do is rewrite what the kernel
	// delivers into something more like the truth. The address used below
	// has very little chance of being the one that caused the fault, but it is
	// malformed, it is clearly not a real pointer, and if it does get printed
	// in real life, people will probably search for it and find this code.
	// There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
	// as I type this comment.
	if(sig == SIGSEGV && SIG_CODE0(info, ctxt) == SI_USER) {
		SIG_CODE0(info, ctxt) = SI_USER+1;
		info->si_addr = (void*)(uintptr)0xb01dfacedebac1eULL;
	}
#endif

	t = &runtime·sigtab[sig];
	if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = SIG_CODE0(info, ctxt);
		gp->sigcode1 = SIG_CODE1(info, ctxt);
		gp->sigpc = SIG_RIP(info, ctxt);

#ifdef GOOS_darwin
		// Work around Leopard bug that doesn't set FPE_INTDIV.
		// Look at instruction to see if it is a divide.
		// Not necessary in Snow Leopard (si_code will be != 0).
		if(sig == SIGFPE && gp->sigcode0 == 0) {
			byte *pc;
			pc = (byte*)gp->sigpc;
			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
				pc++;
			else if(pc[0] == 0x66)	// 16-bit instruction prefix
				pc++;
			if(pc[0] == 0xF6 || pc[0] == 0xF7)
				gp->sigcode0 = FPE_INTDIV;
		}
#endif

		// Only push runtime·sigpanic if rip != 0.
		// If rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(SIG_RIP(info, ctxt) != 0) {
			sp = (uintptr*)SIG_RSP(info, ctxt);
			if(sizeof(uintreg) > sizeof(uintptr))
				*--sp = 0;
			*--sp = SIG_RIP(info, ctxt);
			SIG_RSP(info, ctxt) = (uintptr)sp;
		}
		SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
		return;
	}

	if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

	g->m->throwing = 1;
	g->m->caughtsig = gp;
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
	if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
		runtime·printf("signal arrived during cgo execution\n");
		gp = g->m->lockedg;
	}
	runtime·printf("\n");

	if(runtime·gotraceback(&crash)){
		runtime·goroutineheader(gp);
		runtime·traceback(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
		runtime·tracebackothers(gp);
		runtime·printf("\n");
		runtime·dumpregs(info, ctxt);
	}
	
	if(crash)
		runtime·crash();

	runtime·exit(2);
}