func Test5337(t *testing.T) { test5337(t) }
func Test5548(t *testing.T) { test5548(t) }
func Test5603(t *testing.T) { test5603(t) }
+func Test3250(t *testing.T) { test3250(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void *thread(void *p) {
+ (void)p;
+ const int M = 100;
+ int i;
+ for (i = 0; i < M; i++) {
+ pthread_kill(pthread_self(), SIGCHLD);
+ usleep(rand() % 20 + 5);
+ }
+ return NULL;
+}
+void testSendSIG() {
+ const int N = 20;
+ int i;
+ pthread_t tid[N];
+ for (i = 0; i < N; i++) {
+ usleep(rand() % 200 + 100);
+ pthread_create(&tid[i], 0, thread, NULL);
+ }
+ for (i = 0; i < N; i++)
+ pthread_join(tid[i], 0);
+}
+*/
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func test3250(t *testing.T) {
+ const (
+ thres = 5
+ sig = syscall.SIGCHLD
+ )
+ type result struct {
+ n int
+ sig os.Signal
+ }
+ var (
+ sigCh = make(chan os.Signal, 10)
+ waitStart = make(chan struct{})
+ waitDone = make(chan result)
+ )
+
+ signal.Notify(sigCh, sig)
+
+ go func() {
+ n := 0
+ alarm := time.After(time.Second * 3)
+ for {
+ select {
+ case <-waitStart:
+ waitStart = nil
+ case v := <-sigCh:
+ n++
+ if v != sig || n > thres {
+ waitDone <- result{n, v}
+ return
+ }
+ case <-alarm:
+ waitDone <- result{n, sig}
+ return
+ }
+ }
+ }()
+
+ waitStart <- struct{}{}
+ C.testSendSIG()
+ r := <-waitDone
+ if r.sig != sig {
+ t.Fatalf("received signal %v, but want %v", r.sig, sig)
+ }
+ t.Logf("got %d signals\n", r.n)
+ if r.n <= thres {
+ t.Fatalf("expected more than %d", thres)
+ }
+}
--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test3250(t *testing.T) {}
runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil);
}
-#pragma dataflag 16 // no pointers
-static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag 7
-void
-runtime·badsignal(int32 sig)
-{
- int32 len;
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- runtime·write(2, badsignal, sizeof badsignal - 1);
- if (0 <= sig && sig < NSIG) {
- // Can't call findnull() because it will split stack.
- for(len = 0; runtime·sigtab[sig].name[len]; len++)
- ;
- runtime·write(2, runtime·sigtab[sig].name, len);
- }
- runtime·write(2, "\n", 1);
- runtime·exit(1);
-}
-
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
USED(on);
}
-#pragma dataflag 16 // no pointers
-static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag 7
-void
-runtime·badsignal(int32 sig)
-{
- int32 len;
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- runtime·write(2, badsignal, sizeof badsignal - 1);
- if (0 <= sig && sig < NSIG) {
- // Can't call findnull() because it will split stack.
- for(len = 0; runtime·sigtab[sig].name[len]; len++)
- ;
- runtime·write(2, runtime·sigtab[sig].name, len);
- }
- runtime·write(2, "\n", 1);
- runtime·exit(1);
-}
-
extern void runtime·sigtramp(void);
typedef struct sigaction {
USED(on);
}
-#pragma dataflag 16 // no pointers
-static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag 7
-void
-runtime·badsignal(int32 sig)
-{
- int32 len;
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- runtime·write(2, badsignal, sizeof badsignal - 1);
- if (0 <= sig && sig < NSIG) {
- // Can't call findnull() because it will split stack.
- for(len = 0; runtime·sigtab[sig].name[len]; len++)
- ;
- runtime·write(2, runtime·sigtab[sig].name, len);
- }
- runtime·write(2, "\n", 1);
- runtime·exit(1);
-}
-
#ifdef GOARCH_386
#define sa_handler k_sa_handler
#endif
USED(on);
}
-#pragma dataflag 16 // no pointers
-static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag 7
-void
-runtime·badsignal(int32 sig)
-{
- int32 len;
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- runtime·write(2, badsignal, sizeof badsignal - 1);
- if (0 <= sig && sig < NSIG) {
- // Can't call findnull() because it will split stack.
- for(len = 0; runtime·sigtab[sig].name[len]; len++)
- ;
- runtime·write(2, runtime·sigtab[sig].name, len);
- }
- runtime·write(2, "\n", 1);
- runtime·exit(1);
-}
-
extern void runtime·sigtramp(void);
typedef struct sigaction {
USED(on);
}
-#pragma dataflag 16 // no pointers
-static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-#pragma textflag 7
-void
-runtime·badsignal(int32 sig)
-{
- int32 len;
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- runtime·write(2, badsignal, sizeof badsignal - 1);
- if (0 <= sig && sig < NSIG) {
- // Can't call findnull() because it will split stack.
- for(len = 0; runtime·sigtab[sig].name[len]; len++)
- ;
- runtime·write(2, runtime·sigtab[sig].name, len);
- }
- runtime·write(2, "\n", 1);
- runtime·exit(1);
-}
-
extern void runtime·sigtramp(void);
typedef struct sigaction {
// This runs on a foreign stack, without an m or a g. No stack split.
#pragma textflag 7
void
-runtime·badsignal(void)
+runtime·badsignal2(void)
{
runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL);
runtime·exits(badsignal);
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "cgocall.h"
static struct {
Note;
sig.wanted[s/32] &= ~(1U<<(s&31));
runtime·sigdisable(s);
}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badsignal(uintptr sig)
+{
+ runtime·cgocallback((void (*)(void))runtime·sigsend, &sig, sizeof(sig));
+}
// check that m exists
MOVL m(CX), BP
CMPL BP, $0
- JNE 5(PC)
+ JNE 6(PC)
MOVL sig+8(FP), BX
MOVL BX, 0(SP)
- CALL runtime·badsignal(SB)
- RET
+ MOVL $runtime·badsignal(SB), AX
+ CALL AX
+ JMP sigtramp_ret
// save g
MOVL g(CX), DI
MOVL 20(SP), DI
MOVL DI, g(CX)
+sigtramp_ret:
// call sigreturn
MOVL context+16(FP), CX
MOVL style+4(FP), BX
TEXT runtime·sigtramp(SB),7,$64
get_tls(BX)
+ MOVQ R8, 32(SP) // save ucontext
+ MOVQ SI, 40(SP) // save infostyle
+
// check that m exists
MOVQ m(BX), BP
CMPQ BP, $0
- JNE 4(PC)
+ JNE 5(PC)
MOVL DX, 0(SP)
- CALL runtime·badsignal(SB)
- RET
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
+ JMP sigtramp_ret
// save g
MOVQ g(BX), R10
MOVQ R8, 16(SP)
MOVQ R10, 24(SP)
- MOVQ R8, 32(SP) // save ucontext
- MOVQ SI, 40(SP) // save infostyle
CALL DI
// restore g
MOVQ 48(SP), R10
MOVQ R10, g(BX)
+sigtramp_ret:
// call sigreturn
MOVL $(0x2000000+184), AX // sigreturn(ucontext, infostyle)
MOVQ 32(SP), DI // saved ucontext
// check that m exists
MOVL m(CX), BX
CMPL BX, $0
- JNE 5(PC)
+ JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
- CALL runtime·badsignal(SB)
- RET
+ MOVL $runtime·badsignal(SB), AX
+ CALL AX
+ JMP sigtramp_ret
// save g
MOVL g(CX), DI
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
-
+
+sigtramp_ret:
// call sigreturn
MOVL context+8(FP), AX
MOVL $0, 0(SP) // syscall gap
TEXT runtime·sigtramp(SB),7,$64
get_tls(BX)
-
+
// check that m exists
MOVQ m(BX), BP
CMPQ BP, $0
- JNE 4(PC)
+ JNE 5(PC)
MOVQ DI, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
MOVQ SI, 8(SP)
MOVQ DX, 16(SP)
MOVQ R10, 24(SP)
-
+
CALL runtime·sighandler(SB)
// restore g
BL.NE (R0)
CMP $0, m
- BNE 3(PC)
+ BNE 4(PC)
// signal number is already prepared in 4(R13)
- BL runtime·badsignal(SB)
+ MOVW $runtime·badsignal(SB), R11
+ BL (R11)
RET
// save g
// check that m exists
MOVL m(CX), BX
CMPL BX, $0
- JNE 5(PC)
+ JNE 6(PC)
MOVL sig+0(FP), BX
MOVL BX, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVL $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
// check that m exists
MOVQ m(BX), BP
CMPQ BP, $0
- JNE 4(PC)
+ JNE 5(PC)
MOVQ DI, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
BL.NE (R0)
CMP $0, m
- BNE 3(PC)
+ BNE 4(PC)
// signal number is already prepared in 4(R13)
- BL runtime·badsignal(SB)
+ MOVW $runtime·badsignal(SB), R11
+ BL (R11)
RET
// save g
// check that m exists
MOVL m(CX), BX
CMPL BX, $0
- JNE 5(PC)
+ JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVL $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
// check that m exists
MOVQ m(BX), BP
CMPQ BP, $0
- JNE 4(PC)
+ JNE 5(PC)
MOVQ DI, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
BL.NE (R0)
CMP $0, m
- BNE 3(PC)
+ BNE 4(PC)
// signal number is already prepared in 4(R13)
- BL runtime·badsignal(SB)
+ MOVW $runtime·badsignal(SB), R11
+ BL (R11)
RET
// save g
// check that m exists
MOVL m(CX), BX
CMPL BX, $0
- JNE 5(PC)
+ JNE 6(PC)
MOVL signo+0(FP), BX
MOVL BX, 0(SP)
- CALL runtime·badsignal(SB)
- RET
+ MOVL $runtime·badsignal(SB), AX
+ CALL AX
+ JMP sigtramp_ret
// save g
MOVL g(CX), DI
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
-
+
+sigtramp_ret:
// call sigreturn
MOVL context+8(FP), AX
MOVL $0, 0(SP) // syscall gap
// check that m exists
MOVQ m(BX), BP
CMPQ BP, $0
- JNE 4(PC)
+ JNE 5(PC)
MOVQ DI, 0(SP)
- CALL runtime·badsignal(SB)
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
RET
// save g
MOVL m(AX), BX
CMPL BX, $0
JNE 3(PC)
- CALL runtime·badsignal(SB) // will exit
+ CALL runtime·badsignal2(SB) // will exit
RET
// save args
MOVQ m(AX), BX
CMPQ BX, $0
JNE 3(PC)
- CALL runtime·badsignal(SB) // will exit
+ CALL runtime·badsignal2(SB) // will exit
RET
// save args