1
0
mirror of https://github.com/golang/go synced 2024-11-25 10:17:57 -07:00

cgo, runtime: diagnose callback on non-Go thread

Before:
$ go run x.go
signal 11 (core dumped)
$

After:
$ go run x.go
runtime: cgo callback on thread not created by Go.
signal 11 (core dumped)
$

For issue 3068.
Not a fix, but as much of a fix as we can do before Go 1.

R=golang-dev, rogpeppe, gri
CC=golang-dev
https://golang.org/cl/5781047
This commit is contained in:
Russ Cox 2012-03-08 12:12:40 -05:00
parent 9b7b574edc
commit 9b73238daa
10 changed files with 98 additions and 2 deletions

View File

@ -573,8 +573,9 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
fmt.Fprintf(fc, "#pragma dynexport %s %s\n", goname, goname)
fmt.Fprintf(fc, "extern void ·%s();\n", goname)
fmt.Fprintf(fc, "\nvoid\n")
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)

View File

@ -425,6 +425,14 @@ TEXT runtime·cgocallback(SB),7,$12
// Save current m->g0->sched.sp on stack and then set it to SP.
get_tls(CX)
MOVL m(CX), BP
// If m is nil, it is almost certainly because we have been called
// on a thread that Go did not create. We're going to crash as
// soon as we try to use m; instead, try to print a nice error and exit.
CMPL BP, $0
JNE 2(PC)
CALL runtime·badcallback(SB)
MOVL m_g0(BP), SI
PUSHL (g_sched+gobuf_sp)(SI)
MOVL SP, (g_sched+gobuf_sp)(SI)

View File

@ -471,6 +471,14 @@ TEXT runtime·cgocallback(SB),7,$24
// Save current m->g0->sched.sp on stack and then set it to SP.
get_tls(CX)
MOVQ m(CX), BP
// If m is nil, it is almost certainly because we have been called
// on a thread that Go did not create. We're going to crash as
// soon as we try to use m; instead, try to print a nice error and exit.
CMPQ BP, $0
JNE 2(PC)
CALL runtime·badcallback(SB)
MOVQ m_g0(BP), SI
PUSHQ (g_sched+gobuf_sp)(SI)
MOVQ SP, (g_sched+gobuf_sp)(SI)

View File

@ -477,3 +477,13 @@ runtime·setprof(bool on)
else
runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·write(2, badcallback, sizeof badcallback - 1);
}

View File

@ -195,3 +195,13 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·write(2, badcallback, sizeof badcallback - 1);
}

View File

@ -255,3 +255,13 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·write(2, badcallback, sizeof badcallback - 1);
}

View File

@ -213,3 +213,13 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·write(2, badcallback, sizeof badcallback - 1);
}

View File

@ -213,3 +213,13 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·write(2, badcallback, sizeof badcallback - 1);
}

View File

@ -247,3 +247,13 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
runtime·pwrite(2, badcallback, sizeof badcallback - 1, -1LL);
}

View File

@ -422,3 +422,22 @@ runtime·setprof(bool on)
{
USED(on);
}
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
runtime·badcallback(void)
{
uint32 written;
runtime·stdcall(
runtime·WriteFile, 5,
runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12), // stderr
badcallback,
(uintptr)(sizeof badcallback - 1),
&written,
nil
);
}