]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.4] runtime: fix SIGPROF change
authorRuss Cox <rsc@golang.org>
Wed, 14 Jan 2015 05:54:50 +0000 (00:54 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 14 Jan 2015 06:14:09 +0000 (06:14 +0000)
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 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 <alex.brainman@gmail.com>
(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 <minux@golang.org>
(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 <bradfitz@golang.org>
(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 <bradfitz@golang.org>
(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 <minux@golang.org>
(cherry picked from commit 1ebfb082a7a5cc31efd572fd88549048a82a5c1c)

---

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>
src/runtime/cgo/gcc_openbsd_386.c
src/runtime/cgo/gcc_openbsd_amd64.c
src/runtime/crash_cgo_test.go
src/runtime/defs_windows.go
src/runtime/os_plan9.go
src/runtime/sigqueue.go
src/runtime/syscall_windows.go

index 582e943f34c4c8dc900f3e42d6736b82d4971a97..c4be9a00969e57332020048f351e47d2b400a992 100644 (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());
-               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);
 }
index 35b359bbaf3fd6e7df7ecaa4e3f389e8911e7ff1..8522cd48c4ac9fec18e06c53fe850ef91da4d6dc 100644 (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());
-               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);
 }
index 98c4c1c0d45b901296d09cb7ef7ecf517b6b85cb..29f90fa36d27fc521c008ad71b923b103334bd52 100644 (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"
index 7ce67974141c08ee53677a57b4c80675b1674516..5dfb83a7cf6de98a255422ddeeb2c36b530ebd0b 100644 (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
index 20e47bf42e5cd20bf451be7e0c3c1dc61f12949f..10e5531ecc82eb811cbae018b3a8a71542901c1e 100644 (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
index d2fc5729da03196f979e28d8dc8628673d38360b..fed4560fe3399c8df93c51f3043d71f758e47795 100644 (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))
index efbcab510dad875dc2ee8decd33b96304a5ff43f..5b76ad573c31df384ee5d00a21424e11ba0f5958 100644 (file)
@@ -8,6 +8,8 @@ import (
        "unsafe"
 )
 
+const _SIGPROF = 0 // dummy value for badsignal
+
 type callbacks struct {
        lock mutex
        ctxt [cb_max]*wincallbackcontext