Commit 5146a93e authored by Russ Cox's avatar Russ Cox

runtime: accept GOTRACEBACK=crash to mean 'crash after panic'

This provides a way to generate core dumps when people need them.
The settings are:

        GOTRACEBACK=0  no traceback on panic, just exit
        GOTRACEBACK=1  default - traceback on panic, then exit
        GOTRACEBACK=2  traceback including runtime frames on panic, then exit
        GOTRACEBACK=crash traceback including runtime frames on panic, then crash

Fixes #3257.

R=golang-dev, devon.odell, r, daniel.morsing, ality
CC=golang-dev
https://golang.org/cl/7666044
parent f6a95259
...@@ -3,10 +3,54 @@ ...@@ -3,10 +3,54 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
/* /*
Package runtime contains operations that interact with Go's runtime system, Package runtime contains operations that interact with Go's runtime system,
such as functions to control goroutines. It also includes the low-level type information such as functions to control goroutines. It also includes the low-level type information
used by the reflect package; see reflect's documentation for the programmable used by the reflect package; see reflect's documentation for the programmable
interface to the run-time type system. interface to the run-time type system.
Environment Variables
The following environment variables ($name or %name%, depending on the host
operating system) control the run-time behavior of Go programs. The meanings
and use may change from release to release.
The GOGC variable sets the initial garbage collection target percentage.
A collection is triggered when the ratio of freshly allocated data to live data
remaining after the previous collection reaches this percentage. The default
is GOGC=100. Setting GOGC=off disables the garbage collector entirely.
The runtime/debug package's SetGCPercent function allows changing this
percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
The GOGCTRACE variable controls debug output from the garbage collector.
Setting GOGCTRACE=1 causes the garbage collector to emit a single line to standard
error at each collection, summarizing the amount of memory collected and the
length of the pause. Setting GOGCTRACE=2 emits the same summary but also
repeats each collection.
The GOMAXPROCS variable limits the number of operating system threads that
can execute user-level Go code simultaneously. There is no limit to the number of threads
that can be blocked in system calls on behalf of Go code; those do not count against
the GOMAXPROCS limit. This package's GOMAXPROCS function queries and changes
the limit.
The GOTRACEBACK variable controls the amount of output generated when a Go
program fails due to an unrecovered panic or an unexpected runtime condition.
By default, a failure prints a stack trace for every extant goroutine, eliding functions
internal to the run-time system, and then exits with exit code 2.
If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely.
If GOTRACEBACK=1, the default behavior is used.
If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions.
If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions,
and if possible the program crashes in an operating-specific manner instead of
exiting. For example, on Unix systems, the program raises SIGABRT to trigger a
core dump.
The GOARCH, GOOS, GOPATH, and GOROOT environment variables complete
the set of Go environment variables. They influence the building of Go programs
(see http://golang.org/cmd/go and http://golang.org/pkg/go/build).
GOARCH, GOOS, and GOROOT are recorded at compile time and made available by
constants or functions in this package, but they do not influence the execution
of the run-time system.
*/ */
package runtime package runtime
......
...@@ -91,6 +91,13 @@ runtime·osinit(void) ...@@ -91,6 +91,13 @@ runtime·osinit(void)
runtime·notify(runtime·sigtramp); runtime·notify(runtime·sigtramp);
} }
void
runtime·crash(void)
{
runtime·notify(nil);
*(int32*)0 = 0;
}
void void
runtime·get_random_data(byte **rnd, int32 *rnd_len) runtime·get_random_data(byte **rnd, int32 *rnd_len)
{ {
......
...@@ -28,6 +28,7 @@ runtime·dumpregs(Ureg *u) ...@@ -28,6 +28,7 @@ runtime·dumpregs(Ureg *u)
int32 int32
runtime·sighandler(void *v, int8 *s, G *gp) runtime·sighandler(void *v, int8 *s, G *gp)
{ {
bool crash;
Ureg *ureg; Ureg *ureg;
uintptr *sp; uintptr *sp;
SigTab *sig, *nsig; SigTab *sig, *nsig;
...@@ -93,11 +94,15 @@ Throw: ...@@ -93,11 +94,15 @@ Throw:
runtime·printf("PC=%X\n", ureg->pc); runtime·printf("PC=%X\n", ureg->pc);
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()) { if(runtime·gotraceback(&crash)) {
runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp); runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(ureg); runtime·dumpregs(ureg);
} }
if(crash)
runtime·crash();
runtime·goexitsall(""); runtime·goexitsall("");
runtime·exits(s); runtime·exits(s);
......
...@@ -36,6 +36,7 @@ runtime·dumpregs(Ureg *u) ...@@ -36,6 +36,7 @@ runtime·dumpregs(Ureg *u)
int32 int32
runtime·sighandler(void *v, int8 *s, G *gp) runtime·sighandler(void *v, int8 *s, G *gp)
{ {
bool crash;
Ureg *ureg; Ureg *ureg;
uintptr *sp; uintptr *sp;
SigTab *sig, *nsig; SigTab *sig, *nsig;
...@@ -101,11 +102,15 @@ Throw: ...@@ -101,11 +102,15 @@ Throw:
runtime·printf("PC=%X\n", ureg->ip); runtime·printf("PC=%X\n", ureg->ip);
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()) { if(runtime·gotraceback(&crash)) {
runtime·traceback((void*)ureg->ip, (void*)ureg->sp, 0, gp); runtime·traceback((void*)ureg->ip, (void*)ureg->sp, 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(ureg); runtime·dumpregs(ureg);
} }
if(crash)
runtime·crash();
runtime·goexitsall(""); runtime·goexitsall("");
runtime·exits(s); runtime·exits(s);
......
...@@ -455,3 +455,16 @@ int32 runtime·badcallbacklen = sizeof runtime·badcallbackmsg - 1; ...@@ -455,3 +455,16 @@ int32 runtime·badcallbacklen = sizeof runtime·badcallbackmsg - 1;
int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n"; int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n";
int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1; int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1;
void
runtime·crash(void)
{
// TODO: This routine should do whatever is needed
// to make the Windows program abort/crash as it
// would if Go was not intercepting signals.
// On Unix the routine would remove the custom signal
// handler and then raise a signal (like SIGABRT).
// Something like that should happen here.
// It's okay to leave this empty for now: if crash returns
// the ordinary exit-after-panic happens.
}
...@@ -27,6 +27,7 @@ runtime·dumpregs(Context *r) ...@@ -27,6 +27,7 @@ runtime·dumpregs(Context *r)
uint32 uint32
runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
{ {
bool crash;
uintptr *sp; uintptr *sp;
switch(info->ExceptionCode) { switch(info->ExceptionCode) {
...@@ -74,11 +75,15 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) ...@@ -74,11 +75,15 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
} }
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, gp); runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(r); runtime·dumpregs(r);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
return 0; return 0;
......
...@@ -35,6 +35,7 @@ runtime·dumpregs(Context *r) ...@@ -35,6 +35,7 @@ runtime·dumpregs(Context *r)
uint32 uint32
runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
{ {
bool crash;
uintptr *sp; uintptr *sp;
switch(info->ExceptionCode) { switch(info->ExceptionCode) {
...@@ -81,11 +82,14 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) ...@@ -81,11 +82,14 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
} }
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)r->Rip, (void*)r->Rsp, 0, gp); runtime·traceback((void*)r->Rip, (void*)r->Rsp, 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(r); runtime·dumpregs(r);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
return 0; return 0;
......
...@@ -402,12 +402,13 @@ void ...@@ -402,12 +402,13 @@ void
runtime·dopanic(int32 unused) runtime·dopanic(int32 unused)
{ {
static bool didothers; static bool didothers;
bool crash;
if(g->sig != 0) if(g->sig != 0)
runtime·printf("[signal %x code=%p addr=%p pc=%p]\n", runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
g->sig, g->sigcode0, g->sigcode1, g->sigpc); g->sig, g->sigcode0, g->sigcode1, g->sigpc);
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
if(g != m->g0) { if(g != m->g0) {
runtime·printf("\n"); runtime·printf("\n");
runtime·goroutineheader(g); runtime·goroutineheader(g);
...@@ -428,6 +429,9 @@ runtime·dopanic(int32 unused) ...@@ -428,6 +429,9 @@ runtime·dopanic(int32 unused)
runtime·lock(&deadlock); runtime·lock(&deadlock);
runtime·lock(&deadlock); runtime·lock(&deadlock);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
} }
......
...@@ -232,7 +232,7 @@ runtime·tracebackothers(G *me) ...@@ -232,7 +232,7 @@ runtime·tracebackothers(G *me)
G *gp; G *gp;
int32 traceback; int32 traceback;
traceback = runtime·gotraceback(); traceback = runtime·gotraceback(nil);
for(gp = runtime·allg; gp != nil; gp = gp->alllink) { for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
if(gp == me || gp->status == Gdead) if(gp == me || gp->status == Gdead)
continue; continue;
......
...@@ -17,14 +17,27 @@ enum { ...@@ -17,14 +17,27 @@ enum {
*/ */
void runtime·sigpanic(void); void runtime·sigpanic(void);
// The GOTRACEBACK environment variable controls the
// behavior of a Go program that is crashing and exiting.
// GOTRACEBACK=0 suppress all tracebacks
// GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames
// GOTRACEBACK=2 show tracebacks including runtime frames
// GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc)
int32 int32
runtime·gotraceback(void) runtime·gotraceback(bool *crash)
{ {
byte *p; byte *p;
if(crash != nil)
*crash = false;
p = runtime·getenv("GOTRACEBACK"); p = runtime·getenv("GOTRACEBACK");
if(p == nil || p[0] == '\0') if(p == nil || p[0] == '\0')
return 1; // default is on return 1; // default is on
if(runtime·strcmp(p, (byte*)"crash") == 0) {
if(crash != nil)
*crash = true;
return 2; // extra information
}
return runtime·atoi(p); return runtime·atoi(p);
} }
......
...@@ -699,7 +699,7 @@ String runtime·gostringw(uint16*); ...@@ -699,7 +699,7 @@ String runtime·gostringw(uint16*);
void runtime·initsig(void); void runtime·initsig(void);
void runtime·sigenable(uint32 sig); void runtime·sigenable(uint32 sig);
void runtime·sigdisable(uint32 sig); void runtime·sigdisable(uint32 sig);
int32 runtime·gotraceback(void); int32 runtime·gotraceback(bool *crash);
void runtime·goroutineheader(G*); void runtime·goroutineheader(G*);
void runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp); void runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp);
void runtime·tracebackothers(G*); void runtime·tracebackothers(G*);
...@@ -793,6 +793,7 @@ G* runtime·netpoll(bool); ...@@ -793,6 +793,7 @@ G* runtime·netpoll(bool);
void runtime·netpollinit(void); void runtime·netpollinit(void);
int32 runtime·netpollopen(int32, PollDesc*); int32 runtime·netpollopen(int32, PollDesc*);
void runtime·netpollready(G**, PollDesc*, int32); void runtime·netpollready(G**, PollDesc*, int32);
void runtime·crash(void);
#pragma varargck argpos runtime·printf 1 #pragma varargck argpos runtime·printf 1
#pragma varargck type "d" int32 #pragma varargck type "d" int32
......
...@@ -36,6 +36,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) ...@@ -36,6 +36,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{ {
uintptr *sp; uintptr *sp;
SigTab *t; SigTab *t;
bool crash;
if(sig == SIGPROF) { if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal) if(gp != m->g0 && gp != m->gsignal)
...@@ -109,11 +110,14 @@ Throw: ...@@ -109,11 +110,14 @@ Throw:
} }
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)SIG_EIP(info, ctxt), (void*)SIG_ESP(info, ctxt), 0, gp); runtime·traceback((void*)SIG_EIP(info, ctxt), (void*)SIG_ESP(info, ctxt), 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(info, ctxt); runtime·dumpregs(info, ctxt);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
} }
...@@ -44,6 +44,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) ...@@ -44,6 +44,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{ {
uintptr *sp; uintptr *sp;
SigTab *t; SigTab *t;
bool crash;
if(sig == SIGPROF) { if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal) if(gp != m->g0 && gp != m->gsignal)
...@@ -119,11 +120,14 @@ Throw: ...@@ -119,11 +120,14 @@ Throw:
} }
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)SIG_RIP(info, ctxt), (void*)SIG_RSP(info, ctxt), 0, gp); runtime·traceback((void*)SIG_RIP(info, ctxt), (void*)SIG_RSP(info, ctxt), 0, gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·dumpregs(info, ctxt); runtime·dumpregs(info, ctxt);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
} }
...@@ -43,6 +43,7 @@ void ...@@ -43,6 +43,7 @@ void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{ {
SigTab *t; SigTab *t;
bool crash;
if(sig == SIGPROF) { if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal) if(gp != m->g0 && gp != m->gsignal)
...@@ -109,12 +110,15 @@ Throw: ...@@ -109,12 +110,15 @@ Throw:
} }
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp); runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp);
runtime·tracebackothers(gp); runtime·tracebackothers(gp);
runtime·printf("\n"); runtime·printf("\n");
runtime·dumpregs(info, ctxt); runtime·dumpregs(info, ctxt);
} }
if(crash)
runtime·crash();
runtime·exit(2); runtime·exit(2);
} }
...@@ -98,5 +98,23 @@ void ...@@ -98,5 +98,23 @@ void
os·sigpipe(void) os·sigpipe(void)
{ {
runtime·setsig(SIGPIPE, SIG_DFL, false); runtime·setsig(SIGPIPE, SIG_DFL, false);
runtime·raisesigpipe(); runtime·raise(SIGPIPE);
}
void
runtime·crash(void)
{
#ifdef GOOS_darwin
// OS X core dumps are linear dumps of the mapped memory,
// from the first virtual byte to the last, with zeros in the gaps.
// Because of the way we arrange the address space on 64-bit systems,
// this means the OS X core file will be >128 GB and even on a zippy
// workstation can take OS X well over an hour to write (uninterruptible).
// Save users from making that mistake.
if(sizeof(void*) == 8)
return;
#endif
runtime·setsig(SIGABRT, SIG_DFL, false);
runtime·raise(SIGABRT);
} }
...@@ -10,4 +10,5 @@ void runtime·setsig(int32, GoSighandler*, bool); ...@@ -10,4 +10,5 @@ void runtime·setsig(int32, GoSighandler*, bool);
GoSighandler* runtime·getsig(int32); GoSighandler* runtime·getsig(int32);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp); void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·raisesigpipe(void); void runtime·raise(int32);
...@@ -670,6 +670,6 @@ runtime·showframe(Func *f, bool current) ...@@ -670,6 +670,6 @@ runtime·showframe(Func *f, bool current)
if(current && m->throwing > 0) if(current && m->throwing > 0)
return 1; return 1;
if(traceback < 0) if(traceback < 0)
traceback = runtime·gotraceback(); traceback = runtime·gotraceback(nil);
return traceback > 1 || f != nil && contains(f->name, ".") && !hasprefix(f->name, "runtime."); return traceback > 1 || f != nil && contains(f->name, ".") && !hasprefix(f->name, "runtime.");
} }
...@@ -44,13 +44,14 @@ TEXT runtime·write(SB),7,$0 ...@@ -44,13 +44,14 @@ TEXT runtime·write(SB),7,$0
INT $0x80 INT $0x80
RET RET
TEXT runtime·raisesigpipe(SB),7,$8 TEXT runtime·raise(SB),7,$16
get_tls(CX) MOVL $20, AX // getpid
MOVL m(CX), DX INT $0x80
MOVL m_procid(DX), DX MOVL AX, 4(SP) // pid
MOVL DX, 0(SP) // thread_port MOVL sig+0(FP), AX
MOVL $13, 4(SP) // signal: SIGPIPE MOVL AX, 8(SP) // signal
MOVL $328, AX // __pthread_kill MOVL $1, 12(SP) // posix
MOVL $37, AX // kill
INT $0x80 INT $0x80
RET RET
......
...@@ -60,12 +60,13 @@ TEXT runtime·write(SB),7,$0 ...@@ -60,12 +60,13 @@ TEXT runtime·write(SB),7,$0
SYSCALL SYSCALL
RET RET
TEXT runtime·raisesigpipe(SB),7,$24 TEXT runtime·raise(SB),7,$24
get_tls(CX) MOVL $(0x2000000+20), AX // getpid
MOVQ m(CX), DX SYSCALL
MOVL $13, DI // arg 1 SIGPIPE MOVQ AX, DI // arg 1 - pid
MOVQ m_procid(DX), SI // arg 2 thread_port MOVL sig+0(FP), SI // arg 2 - signal
MOVL $(0x2000000+328), AX // syscall entry __pthread_kill MOVL $1, DX // arg 3 - posix
MOVL $(0x2000000+37), AX // kill
SYSCALL SYSCALL
RET RET
......
...@@ -81,16 +81,17 @@ TEXT runtime·getrlimit(SB),7,$-4 ...@@ -81,16 +81,17 @@ TEXT runtime·getrlimit(SB),7,$-4
INT $0x80 INT $0x80
RET RET
TEXT runtime·raisesigpipe(SB),7,$12 TEXT runtime·raise(SB),7,$16
// thr_self(&8(SP)) // thr_self(&8(SP))
LEAL 8(SP), AX LEAL 8(SP), AX
MOVL AX, 0(SP) MOVL AX, 4(SP)
MOVL $432, AX MOVL $432, AX
INT $0x80 INT $0x80
// thr_kill(self, SIGPIPE) // thr_kill(self, SIGPIPE)
MOVL 8(SP), AX MOVL 8(SP), AX
MOVL AX, 0(SP) MOVL AX, 4(SP)
MOVL $13, 4(SP) MOVL sig+0(FP), AX
MOVL AX, 8(SP)
MOVL $433, AX MOVL $433, AX
INT $0x80 INT $0x80
RET RET
......
...@@ -95,14 +95,14 @@ TEXT runtime·getrlimit(SB),7,$-8 ...@@ -95,14 +95,14 @@ TEXT runtime·getrlimit(SB),7,$-8
SYSCALL SYSCALL
RET RET
TEXT runtime·raisesigpipe(SB),7,$16 TEXT runtime·raise(SB),7,$16
// thr_self(&8(SP)) // thr_self(&8(SP))
LEAQ 8(SP), DI // arg 1 &8(SP) LEAQ 8(SP), DI // arg 1 &8(SP)
MOVL $432, AX MOVL $432, AX
SYSCALL SYSCALL
// thr_kill(self, SIGPIPE) // thr_kill(self, SIGPIPE)
MOVQ 8(SP), DI // arg 1 id MOVQ 8(SP), DI // arg 1 id
MOVQ $13, SI // arg 2 SIGPIPE MOVL sig+0(FP), SI // arg 2
MOVL $433, AX MOVL $433, AX
SYSCALL SYSCALL
RET RET
......
...@@ -87,13 +87,13 @@ TEXT runtime·getrlimit(SB),7,$-8 ...@@ -87,13 +87,13 @@ TEXT runtime·getrlimit(SB),7,$-8
SWI $194 SWI $194
RET RET
TEXT runtime·raisesigpipe(SB),7,$8 TEXT runtime·raise(SB),7,$8
// thr_self(&4(R13)) // thr_self(&4(R13))
MOVW $4(R13), R0 // arg 1 &4(R13) MOVW $4(R13), R0 // arg 1 &4(R13)
SWI $432 SWI $432
// thr_kill(self, SIGPIPE) // thr_kill(self, SIGPIPE)
MOVW 4(R13), R0 // arg 1 id MOVW 4(R13), R0 // arg 1 id
MOVW $13, R1 // arg 2 SIGPIPE MOVW sig+0(FP), R1 // arg 2 - signal
SWI $433 SWI $433
RET RET
......
...@@ -77,11 +77,11 @@ TEXT runtime·usleep(SB),7,$8 ...@@ -77,11 +77,11 @@ TEXT runtime·usleep(SB),7,$8
CALL *runtime·_vdso(SB) CALL *runtime·_vdso(SB)
RET RET
TEXT runtime·raisesigpipe(SB),7,$12 TEXT runtime·raise(SB),7,$12
MOVL $224, AX // syscall - gettid MOVL $224, AX // syscall - gettid
CALL *runtime·_vdso(SB) CALL *runtime·_vdso(SB)
MOVL AX, 0(SP) // arg 1 tid MOVL AX, BX // arg 1 tid
MOVL $13, 4(SP) // arg 2 SIGPIPE MOVL sig+0(FP), CX // arg 2 signal
MOVL $238, AX // syscall - tkill MOVL $238, AX // syscall - tkill
CALL *runtime·_vdso(SB) CALL *runtime·_vdso(SB)
RET RET
......
...@@ -75,11 +75,11 @@ TEXT runtime·usleep(SB),7,$16 ...@@ -75,11 +75,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL SYSCALL
RET RET
TEXT runtime·raisesigpipe(SB),7,$12 TEXT runtime·raise(SB),7,$12
MOVL $186, AX // syscall - gettid MOVL $186, AX // syscall - gettid
SYSCALL SYSCALL
MOVL AX, DI // arg 1 tid MOVL AX, DI // arg 1 tid
MOVL $13, SI // arg 2 SIGPIPE MOVL sig+0(FP), SI // arg 2
MOVL $200, AX // syscall - tkill MOVL $200, AX // syscall - tkill
SYSCALL SYSCALL
RET RET
......
...@@ -92,11 +92,11 @@ TEXT runtime·exit1(SB),7,$-4 ...@@ -92,11 +92,11 @@ TEXT runtime·exit1(SB),7,$-4
MOVW $1003, R1 MOVW $1003, R1
MOVW R0, (R1) // fail hard MOVW R0, (R1) // fail hard
TEXT runtime·raisesigpipe(SB),7,$-4 TEXT runtime·raise(SB),7,$-4
MOVW $SYS_gettid, R7 MOVW $SYS_gettid, R7
SWI $0 SWI $0
// arg 1 tid already in R0 from gettid // arg 1 tid already in R0 from gettid
MOVW $13, R1 // arg 2 SIGPIPE MOVW sig+0(FP), R1 // arg 2 - signal
MOVW $SYS_tkill, R7 MOVW $SYS_tkill, R7
SWI $0 SWI $0
RET RET
......
...@@ -61,12 +61,13 @@ TEXT runtime·usleep(SB),7,$24 ...@@ -61,12 +61,13 @@ TEXT runtime·usleep(SB),7,$24
INT $0x80 INT $0x80
RET RET
TEXT runtime·raisesigpipe(SB),7,$12 TEXT runtime·raise(SB),7,$12
MOVL $311, AX // sys__lwp_self MOVL $311, AX // sys__lwp_self
INT $0x80 INT $0x80
MOVL $0, 0(SP) MOVL $0, 0(SP)
MOVL AX, 4(SP) // arg 1 - target MOVL AX, 4(SP) // arg 1 - target
MOVL $13, 8(SP) // arg 2 - signo == SIGPIPE MOVL sig+0(FP), AX
MOVL AX, 8(SP) // arg 2 - signo
MOVL $318, AX // sys__lwp_kill MOVL $318, AX // sys__lwp_kill
INT $0x80 INT $0x80
RET RET
......
...@@ -125,11 +125,11 @@ TEXT runtime·usleep(SB),7,$16 ...@@ -125,11 +125,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL SYSCALL
RET RET
TEXT runtime·raisesigpipe(SB),7,$16 TEXT runtime·raise(SB),7,$16
MOVL $311, AX // sys__lwp_self MOVL $311, AX // sys__lwp_self
SYSCALL SYSCALL
MOVQ AX, DI // arg 1 - target MOVQ AX, DI // arg 1 - target
MOVQ $13, SI // arg 2 - signo == SIGPIPE MOVL sig+0(FP), SI // arg 2 - signo
MOVL $318, AX // sys__lwp_kill MOVL $318, AX // sys__lwp_kill
SYSCALL SYSCALL
RET RET
......
...@@ -88,9 +88,9 @@ TEXT runtime·usleep(SB),7,$16 ...@@ -88,9 +88,9 @@ TEXT runtime·usleep(SB),7,$16
SWI $0xa001ae // sys_nanosleep SWI $0xa001ae // sys_nanosleep
RET RET
TEXT runtime·raisesigpipe(SB),7,$16 TEXT runtime·raise(SB),7,$16
SWI $0xa00137 // sys__lwp_self, the returned R0 is arg 1 SWI $0xa00137 // sys__lwp_self, the returned R0 is arg 1
MOVW $13, R1 // arg 2 - signo == SIGPIPE MOVW sig+0(FP), R1 // arg 2 - signal
SWI $0xa0013e // sys__lwp_kill SWI $0xa0013e // sys__lwp_kill
RET RET
......
...@@ -62,12 +62,13 @@ TEXT runtime·usleep(SB),7,$20 ...@@ -62,12 +62,13 @@ TEXT runtime·usleep(SB),7,$20
INT $0x80 INT $0x80
RET RET
TEXT runtime·raisesigpipe(SB),7,$12 TEXT runtime·raise(SB),7,$12
MOVL $299, AX // sys_getthrid MOVL $299, AX // sys_getthrid
INT $0x80 INT $0x80
MOVL $0, 0(SP) MOVL $0, 0(SP)
MOVL AX, 4(SP) // arg 1 - pid MOVL AX, 4(SP) // arg 1 - pid
MOVL $13, 8(SP) // arg 2 - signum == SIGPIPE MOVL sig+0(FP), AX
MOVL AX, 8(SP) // arg 2 - signum
MOVL $37, AX // sys_kill MOVL $37, AX // sys_kill
INT $0x80 INT $0x80
RET RET
......
...@@ -133,11 +133,11 @@ TEXT runtime·usleep(SB),7,$16 ...@@ -133,11 +133,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL SYSCALL
RET RET
TEXT runtime·raisesigpipe(SB),7,$16 TEXT runtime·raise(SB),7,$16
MOVL $299, AX // sys_getthrid MOVL $299, AX // sys_getthrid
SYSCALL SYSCALL
MOVQ AX, DI // arg 1 - pid MOVQ AX, DI // arg 1 - pid
MOVQ $13, SI // arg 2 - signum == SIGPIPE MOVL sig+0(FP), SI // arg 2 - signum
MOVL $37, AX // sys_kill MOVL $37, AX // sys_kill
SYSCALL SYSCALL
RET RET
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment