From add1ee0ed5e0ace0a7d09d9aed38cbd7063f5f28 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 14 Jan 2015 00:54:50 -0500 Subject: [PATCH] [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 (cherry picked from commit 77cd6197d7561ab7ccbf5d892efb6f97d929546a) --- 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 (cherry picked from commit 1f282385579fc404f1246fd7ffa8b4e517401d19) --- 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 (cherry picked from commit 0b2a74e89cf940e1c4cd91785ff3d744684edc49) --- 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 (cherry picked from commit 2cbe27a27202dca5a643b75c79e25d4cccc3ae67) --- 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 (cherry picked from commit 865e5e98b685eb3a7888f5263021049c0694d16f) --- runtime: remove unnecessary GOOS switch Change-Id: I8f518e273c02110042b08f7c50c3d38a648c8b6e Reviewed-on: https://go-review.googlesource.com/2281 Reviewed-by: Minux Ma (cherry picked from commit 1ebfb082a7a5cc31efd572fd88549048a82a5c1c) --- Change-Id: Ifee9667ca90eda2b074817c319b1b7c66d4f741d Reviewed-on: https://go-review.googlesource.com/2805 Reviewed-by: Minux Ma Reviewed-by: Andrew Gerrand --- src/runtime/cgo/gcc_openbsd_386.c | 40 +++++++++++++++++++++-------- src/runtime/cgo/gcc_openbsd_amd64.c | 40 +++++++++++++++++++++-------- src/runtime/crash_cgo_test.go | 15 ++++++++++- src/runtime/defs_windows.go | 1 + src/runtime/os_plan9.go | 2 ++ src/runtime/sigqueue.go | 2 +- src/runtime/syscall_windows.go | 2 ++ 7 files changed, 78 insertions(+), 24 deletions(-) diff --git a/src/runtime/cgo/gcc_openbsd_386.c b/src/runtime/cgo/gcc_openbsd_386.c index 582e943f34..c4be9a0096 100644 --- a/src/runtime/cgo/gcc_openbsd_386.c +++ b/src/runtime/cgo/gcc_openbsd_386.c @@ -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()); - abort(); - } - sys_pthread_create = dlsym(handle, "pthread_create"); - if(sys_pthread_create == NULL) { - fprintf(stderr, "dlsym: failed to find pthread_create: %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(); } - dlclose(handle); tcb_fixup(1); } diff --git a/src/runtime/cgo/gcc_openbsd_amd64.c b/src/runtime/cgo/gcc_openbsd_amd64.c index 35b359bbaf..8522cd48c4 100644 --- a/src/runtime/cgo/gcc_openbsd_amd64.c +++ b/src/runtime/cgo/gcc_openbsd_amd64.c @@ -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()); - abort(); - } - sys_pthread_create = dlsym(handle, "pthread_create"); - if(sys_pthread_create == NULL) { - fprintf(stderr, "dlsym: failed to find pthread_create: %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(); } - dlclose(handle); tcb_fixup(1); } diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 98c4c1c0d4..29f90fa36d 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -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" diff --git a/src/runtime/defs_windows.go b/src/runtime/defs_windows.go index 7ce6797414..5dfb83a7cf 100644 --- a/src/runtime/defs_windows.go +++ b/src/runtime/defs_windows.go @@ -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 diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 20e47bf42e..10e5531ecc 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -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 diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go index d2fc5729da..fed4560fe3 100644 --- a/src/runtime/sigqueue.go +++ b/src/runtime/sigqueue.go @@ -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)) diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index efbcab510d..5b76ad573c 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -8,6 +8,8 @@ import ( "unsafe" ) +const _SIGPROF = 0 // dummy value for badsignal + type callbacks struct { lock mutex ctxt [cb_max]*wincallbackcontext -- 2.48.1