]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: on NetBSD and DragonFly drop signal stack in new thread
authorIan Lance Taylor <iant@golang.org>
Thu, 21 Jan 2016 20:38:05 +0000 (12:38 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 21 Jan 2016 23:21:47 +0000 (23:21 +0000)
On NetBSD and DragonFly a newly created thread inherits the signal stack
of the creating thread.  This breaks horribly if both threads get a
signal at the same time.  Fix this by dropping the signal stack in the
newly created thread.  The right signal stack will then get installed
later.

Note that cgo code that calls pthread_create will have the wrong,
duplicated, signal stack in the newly created thread.  I don't see any
way to fix that in Go.  People using cgo to call pthread_create will
have to be aware of the problem.

Fixes #13945.
Fixes #13947.

Change-Id: I0c7bd2cdf9ada575d57182ca5e9523060de34931
Reviewed-on: https://go-review.googlesource.com/18814
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/runtime/cgo/gcc_dragonfly_amd64.c
src/runtime/cgo/gcc_netbsd_386.c
src/runtime/cgo/gcc_netbsd_amd64.c
src/runtime/cgo/gcc_netbsd_arm.c
src/runtime/os1_netbsd.go
src/runtime/sys_dragonfly_amd64.s

index f79f652e466e5b4d4ca83a3966a63527e72979a7..f41b9b408a3d1a7274969e75554b214f80f23768 100644 (file)
@@ -56,6 +56,7 @@ static void*
 threadentry(void *v)
 {
        ThreadStart ts;
+       stack_t ss;
 
        ts = *(ThreadStart*)v;
        free(v);
@@ -65,6 +66,17 @@ threadentry(void *v)
         */
        setg_gcc((void*)ts.g);
 
+       // On DragonFly, a new thread inherits the signal stack of the
+       // creating thread.  That confuses minit, so we remove that
+       // signal stack here before calling the regular mstart.  It's
+       // a bit baroque to remove a signal stack here only to add one
+       // in minit, but it's a simple change that keeps DragonFly
+       // working like other OS's.  At this point all signals are
+       // blocked, so there is no race.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_flags = SS_DISABLE;
+       sigaltstack(&ss, nil);
+
        crosscall_amd64(ts.fn);
        return nil;
 }
index 2505e6dc7cf87e407326792b65e34a1d61eef31e..6fc7a122b4b8b506e0720702af66744a47f0a133 100644 (file)
@@ -55,6 +55,7 @@ static void*
 threadentry(void *v)
 {
        ThreadStart ts;
+       stack_t ss;
 
        ts = *(ThreadStart*)v;
        free(v);
@@ -64,6 +65,17 @@ threadentry(void *v)
         */
        setg_gcc((void*)ts.g);
 
+       // On NetBSD, a new thread inherits the signal stack of the
+       // creating thread.  That confuses minit, so we remove that
+       // signal stack here before calling the regular mstart.  It's
+       // a bit baroque to remove a signal stack here only to add one
+       // in minit, but it's a simple change that keeps NetBSD
+       // working like other OS's.  At this point all signals are
+       // blocked, so there is no race.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_flags = SS_DISABLE;
+       sigaltstack(&ss, nil);
+
        crosscall_386(ts.fn);
        return nil;
 }
index 8f646502d7a2269c36de14a9b1a20ad0d62b4566..f0ecfac575a47c48bf53b4a5f6cd748a2858010f 100644 (file)
@@ -56,6 +56,7 @@ static void*
 threadentry(void *v)
 {
        ThreadStart ts;
+       stack_t ss;
 
        ts = *(ThreadStart*)v;
        free(v);
@@ -65,6 +66,17 @@ threadentry(void *v)
         */
        setg_gcc((void*)ts.g);
 
+       // On NetBSD, a new thread inherits the signal stack of the
+       // creating thread.  That confuses minit, so we remove that
+       // signal stack here before calling the regular mstart.  It's
+       // a bit baroque to remove a signal stack here only to add one
+       // in minit, but it's a simple change that keeps NetBSD
+       // working like other OS's.  At this point all signals are
+       // blocked, so there is no race.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_flags = SS_DISABLE;
+       sigaltstack(&ss, nil);
+
        crosscall_amd64(ts.fn);
        return nil;
 }
index 7a98c0de24bdfc7cf4fd94c6000f942c5f520f8d..3567aaae725d319aed9bb4b970a2cf30616b1174 100644 (file)
@@ -57,10 +57,22 @@ static void*
 threadentry(void *v)
 {
        ThreadStart ts;
+       stack_t ss;
 
        ts = *(ThreadStart*)v;
        free(v);
 
+       // On NetBSD, a new thread inherits the signal stack of the
+       // creating thread.  That confuses minit, so we remove that
+       // signal stack here before calling the regular mstart.  It's
+       // a bit baroque to remove a signal stack here only to add one
+       // in minit, but it's a simple change that keeps NetBSD
+       // working like other OS's.  At this point all signals are
+       // blocked, so there is no race.
+       memset(&ss, 0, sizeof ss);
+       ss.ss_flags = SS_DISABLE;
+       sigaltstack(&ss, nil);
+
        crosscall_arm1(ts.fn, setg_gcc, (void*)ts.g);
        return nil;
 }
index 42199020e51546150d499e5a387b1db6d52a6a72..9ab39ba97d954e00970fed3f17d64676bb6b1b9f 100644 (file)
@@ -104,7 +104,7 @@ func newosproc(mp *m, stk unsafe.Pointer) {
        uc.uc_link = nil
        uc.uc_sigmask = sigset_all
 
-       lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(mstart))
+       lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(netbsdMstart))
 
        ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid))
        if ret < 0 {
@@ -113,6 +113,19 @@ func newosproc(mp *m, stk unsafe.Pointer) {
        }
 }
 
+// netbsdMStart is the function call that starts executing a newly
+// created thread.  On NetBSD, a new thread inherits the signal stack
+// of the creating thread.  That confuses minit, so we remove that
+// signal stack here before calling the regular mstart.  It's a bit
+// baroque to remove a signal stack here only to add one in minit, but
+// it's a simple change that keeps NetBSD working like other OS's.
+// At this point all signals are blocked, so there is no race.
+//go:nosplit
+func netbsdMstart() {
+       signalstack(nil)
+       mstart()
+}
+
 func osinit() {
        ncpu = getncpu()
 }
index d1b94e1bfdc18edcead2bc25e5a9676da0a4ab1a..4e4d793c43b7387ddfe5b7d5b1cb1ee649a66bf1 100644 (file)
@@ -51,6 +51,18 @@ TEXT runtime·lwp_start(SB),NOSPLIT,$0
        MOVQ    R13, g_m(DI)
        MOVQ    DI, g(CX)
 
+       // On DragonFly, a new thread inherits the signal stack of the
+       // creating thread.  That confuses minit, so we remove that
+       // signal stack here before calling the regular mstart.  It's
+       // a bit baroque to remove a signal stack here only to add one
+       // in minit, but it's a simple change that keeps DragonFly
+       // working like other OS's.  At this point all signals are
+       // blocked, so there is no race.
+       SUBQ    $8, SP
+       MOVQ    $0, 0(SP)
+       CALL    runtime·signalstack(SB)
+       ADDQ    $8, SP
+
        CALL    runtime·stackcheck(SB)
        CALL    runtime·mstart(SB)