[release-branch.go1.4] runtime: fix SIGPROF change

CL 2789 backported a change that required a barrage of followup CLs.
This CL backports all the followup CLs together.

There are manual edits to os_plan9.go and syscall_windows.go to take
the place of edits to defs_windows_{amd64,386}.go and os2_plan9.go
in the original. Those files do not exist in the release branch, but the
definition being added must go somewhere.

Original change descriptions below.

---

runtime/cgo: initialize our pthread_create wrapper earlier on openbsd

This is a genuine bug exposed by our test for issue 9456: our wrapper
for pthread_create is not initialized until we initialize cgo itself,
but it is possible that a static constructor could call pthread_create,
and in that case, it will be calling a nil function pointer.

Fix that by also initializing the sys_pthread_create function pointer
inside our pthread_create wrapper function, and use a pthread_once to
make sure it is only initialized once.

Fix build for openbsd.

Change-Id: Ica4da2c21fcaec186fdd3379128ef46f0e767ed7
Reviewed-on: https://go-review.googlesource.com/2232
Reviewed-by: David Crawshaw <crawshaw@golang.org>
(cherry picked from commit 77cd6197d7)

---

runtime: provide a dummy value of _SIGPROF on plan9 and windows

Fixes build on plan9 and windows.

Change-Id: Ic9b02c641ab84e4f6d8149de71b9eb495e3343b2
Reviewed-on: https://go-review.googlesource.com/2233
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
(cherry picked from commit 1f28238557)

---

runtime/cgo: remove unused variable

I missed this one in golang.org/cl/2232 and only tested the patch
on openbsd/amd64.

Change-Id: I4ff437ae0bfc61c989896c01904b6d33f9bdf0ec
Reviewed-on: https://go-review.googlesource.com/2234
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit 0b2a74e89c)

---

runtime: skip TestCgoExternalThreadSIGPROF on OS X 10.6

The test program requires static constructor, which in turn needs
external linking to work, but external linking never works on 10.6.

This should fix the darwin-{386,amd64} builders.

Change-Id: I714fdd3e35f9a7e5f5659cf26367feec9412444f
Reviewed-on: https://go-review.googlesource.com/2235
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 2cbe27a272)

---

runtime: fix TestCgoExternalThreadSIGPROF again

Shell out to `uname -r` this time, so that the test will compile
even if the platform doesn't have syscall.Sysctl.

Change-Id: I3a19ab5d820bdb94586a97f4507b3837d7040525
Reviewed-on: https://go-review.googlesource.com/2271
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 865e5e98b6)

---

runtime: remove unnecessary GOOS switch

Change-Id: I8f518e273c02110042b08f7c50c3d38a648c8b6e
Reviewed-on: https://go-review.googlesource.com/2281
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit 1ebfb082a7)

---

Change-Id: Ifee9667ca90eda2b074817c319b1b7c66d4f741d
Reviewed-on: https://go-review.googlesource.com/2805
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
Russ Cox 2015-01-14 00:54:50 -05:00
parent d9e0ca4055
commit add1ee0ed5
7 changed files with 78 additions and 24 deletions

View File

@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.arg);
}
static void init_pthread_wrapper(void) {
void *handle;
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "runtime/cgo: dlopen failed to load libpthread: %s\n", dlerror());
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
}
static pthread_once_t init_pthread_wrapper_once = PTHREAD_ONCE_INIT;
int
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
struct thread_args *p;
// we must initialize our wrapper in pthread_create, because it is valid to call
// pthread_create in a static constructor, and in fact, our test for issue 9456
// does just that.
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
p = malloc(sizeof(*p));
if(p == NULL) {
errno = ENOMEM;
@ -87,7 +114,6 @@ x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
setg_gcc = setg;
pthread_attr_init(&attr);
@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
tcb_fixup(1);
}

View File

@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.arg);
}
static void init_pthread_wrapper(void) {
void *handle;
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "runtime/cgo: dlopen failed to load libpthread: %s\n", dlerror());
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
}
static pthread_once_t init_pthread_wrapper_once = PTHREAD_ONCE_INIT;
int
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
struct thread_args *p;
// we must initialize our wrapper in pthread_create, because it is valid to call
// pthread_create in a static constructor, and in fact, our test for issue 9456
// does just that.
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
p = malloc(sizeof(*p));
if(p == NULL) {
errno = ENOMEM;
@ -87,7 +114,6 @@ x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
setg_gcc = setg;
pthread_attr_init(&attr);
@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
tcb_fixup(1);
}

View File

@ -7,6 +7,7 @@
package runtime_test
import (
"os/exec"
"runtime"
"strings"
"testing"
@ -52,8 +53,20 @@ func TestCgoExternalThreadPanic(t *testing.T) {
func TestCgoExternalThreadSIGPROF(t *testing.T) {
// issue 9456.
if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
switch runtime.GOOS {
case "plan9", "windows":
t.Skipf("no pthreads on %s", runtime.GOOS)
case "darwin":
// static constructor needs external linking, but we don't support
// external linking on OS X 10.6.
out, err := exec.Command("uname", "-r").Output()
if err != nil {
t.Fatalf("uname -r failed: %v", err)
}
// OS X 10.6 == Darwin 10.x
if strings.HasPrefix(string(out), "10.") {
t.Skipf("no external linking on OS X 10.6")
}
}
got := executeTest(t, cgoExternalThreadSIGPROFSource, nil)
want := "OK\n"

View File

@ -41,6 +41,7 @@ const (
DUPLICATE_SAME_ACCESS = C.DUPLICATE_SAME_ACCESS
THREAD_PRIORITY_HIGHEST = C.THREAD_PRIORITY_HIGHEST
SIGPROF = 0 // dummy value for badsignal
SIGINT = C.SIGINT
CTRL_C_EVENT = C.CTRL_C_EVENT
CTRL_BREAK_EVENT = C.CTRL_BREAK_EVENT

View File

@ -6,6 +6,8 @@ package runtime
import "unsafe"
const _SIGPROF = 0 // dummy value for badsignal
func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
func seek(fd int32, offset int64, whence int32) int64

View File

@ -160,7 +160,7 @@ func badsignal(sig uintptr) {
// call to cgocallback below will bring down the whole process.
// It's better to miss a few SIGPROF signals than to abort in this case.
// See http://golang.org/issue/9456.
if sig == _SIGPROF && needextram != 0 {
if _SIGPROF != 0 && sig == _SIGPROF && needextram != 0 {
return
}
cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))

View File

@ -8,6 +8,8 @@ import (
"unsafe"
)
const _SIGPROF = 0 // dummy value for badsignal
type callbacks struct {
lock mutex
ctxt [cb_max]*wincallbackcontext