Skip to content

Commit a7d2b4d

Browse files
runtime: disable a signal by restoring the original disposition
Fixes #13034. Fixes #13042. Update #9896. Change-Id: I189f381090223dd07086848aac2d69d2c00d80c4 Reviewed-on: https://go-review.googlesource.com/18062 Reviewed-by: Russ Cox <[email protected]>
1 parent 6c8a141 commit a7d2b4d

File tree

9 files changed

+486
-25
lines changed

9 files changed

+486
-25
lines changed

misc/cgo/testcarchive/main3.c

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Test os/signal.Notify and os/signal.Reset.
6+
// This is a lot like misc/cgo/testcshared/main5.c.
7+
8+
#include <signal.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <sched.h>
13+
14+
#include "libgo3.h"
15+
16+
static void die(const char* msg) {
17+
perror(msg);
18+
exit(EXIT_FAILURE);
19+
}
20+
21+
static volatile sig_atomic_t sigioSeen;
22+
23+
static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
24+
sigioSeen = 1;
25+
}
26+
27+
int main(int argc, char** argv) {
28+
int verbose;
29+
struct sigaction sa;
30+
int i;
31+
32+
verbose = argc > 2;
33+
setvbuf(stdout, NULL, _IONBF, 0);
34+
35+
if (verbose) {
36+
printf("calling sigaction\n");
37+
}
38+
39+
memset(&sa, 0, sizeof sa);
40+
sa.sa_sigaction = ioHandler;
41+
if (sigemptyset(&sa.sa_mask) < 0) {
42+
die("sigemptyset");
43+
}
44+
sa.sa_flags = SA_SIGINFO;
45+
if (sigaction(SIGIO, &sa, NULL) < 0) {
46+
die("sigaction");
47+
}
48+
49+
// At this point there should not be a Go signal handler
50+
// installed for SIGIO.
51+
52+
if (verbose) {
53+
printf("raising SIGIO\n");
54+
}
55+
56+
if (raise(SIGIO) < 0) {
57+
die("raise");
58+
}
59+
60+
if (verbose) {
61+
printf("waiting for sigioSeen\n");
62+
}
63+
64+
// Wait until the signal has been delivered.
65+
i = 0;
66+
while (!sigioSeen) {
67+
if (sched_yield() < 0) {
68+
perror("sched_yield");
69+
}
70+
i++;
71+
if (i > 10000) {
72+
fprintf(stderr, "looping too long waiting for signal\n");
73+
exit(EXIT_FAILURE);
74+
}
75+
}
76+
77+
sigioSeen = 0;
78+
79+
// Tell the Go code to catch SIGIO.
80+
81+
if (verbose) {
82+
printf("calling CatchSIGIO\n");
83+
}
84+
85+
CatchSIGIO();
86+
87+
if (verbose) {
88+
printf("raising SIGIO\n");
89+
}
90+
91+
if (raise(SIGIO) < 0) {
92+
die("raise");
93+
}
94+
95+
if (verbose) {
96+
printf("calling SawSIGIO\n");
97+
}
98+
99+
if (!SawSIGIO()) {
100+
fprintf(stderr, "Go handler did not see SIGIO\n");
101+
exit(EXIT_FAILURE);
102+
}
103+
104+
if (sigioSeen != 0) {
105+
fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
106+
exit(EXIT_FAILURE);
107+
}
108+
109+
// Tell the Go code to stop catching SIGIO.
110+
111+
if (verbose) {
112+
printf("calling ResetSIGIO\n");
113+
}
114+
115+
ResetSIGIO();
116+
117+
if (verbose) {
118+
printf("raising SIGIO\n");
119+
}
120+
121+
if (raise(SIGIO) < 0) {
122+
die("raise");
123+
}
124+
125+
if (verbose) {
126+
printf("calling SawSIGIO\n");
127+
}
128+
129+
if (SawSIGIO()) {
130+
fprintf(stderr, "Go handler saw SIGIO after Reset\n");
131+
exit(EXIT_FAILURE);
132+
}
133+
134+
if (verbose) {
135+
printf("waiting for sigioSeen\n");
136+
}
137+
138+
// Wait until the signal has been delivered.
139+
i = 0;
140+
while (!sigioSeen) {
141+
if (sched_yield() < 0) {
142+
perror("sched_yield");
143+
}
144+
i++;
145+
if (i > 10000) {
146+
fprintf(stderr, "looping too long waiting for signal\n");
147+
exit(EXIT_FAILURE);
148+
}
149+
}
150+
151+
printf("PASS\n");
152+
return 0;
153+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import "C"
8+
9+
import (
10+
"os"
11+
"os/signal"
12+
"syscall"
13+
"time"
14+
)
15+
16+
// The channel used to read SIGIO signals.
17+
var sigioChan chan os.Signal
18+
19+
// CatchSIGIO starts catching SIGIO signals.
20+
//export CatchSIGIO
21+
func CatchSIGIO() {
22+
sigioChan = make(chan os.Signal, 1)
23+
signal.Notify(sigioChan, syscall.SIGIO)
24+
}
25+
26+
// ResetSIGIO stops catching SIGIO signals.
27+
//export ResetSIGIO
28+
func ResetSIGIO() {
29+
signal.Reset(syscall.SIGIO)
30+
}
31+
32+
// SawSIGIO returns whether we saw a SIGIO within a brief pause.
33+
//export SawSIGIO
34+
func SawSIGIO() C.int {
35+
select {
36+
case <-sigioChan:
37+
return 1
38+
case <-time.After(100 * time.Millisecond):
39+
return 0
40+
}
41+
}
42+
43+
func main() {
44+
}

misc/cgo/testcarchive/test.bash

+13-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ status=0
3030
GOPATH=$(pwd) go install -buildmode=c-archive libgo
3131
$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c pkg/$(go env GOOS)_$(go env GOARCH)/libgo.a
3232
if ! $bin arg1 arg2; then
33-
echo "FAIL test1"
33+
echo "FAIL test1a"
3434
status=1
3535
fi
3636
rm -f libgo.a libgo.h testp
@@ -41,32 +41,40 @@ rm -f libgo.a libgo.h testp
4141
GOPATH=$(pwd) go build -buildmode=c-archive src/libgo/libgo.go
4242
$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c libgo.a
4343
if ! $bin arg1 arg2; then
44-
echo "FAIL test2"
44+
echo "FAIL test1b"
4545
status=1
4646
fi
4747
rm -f libgo.a libgo.h testp
4848

4949
GOPATH=$(pwd) go build -buildmode=c-archive -o libgo.a libgo
5050
$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c libgo.a
5151
if ! $bin arg1 arg2; then
52-
echo "FAIL test3"
52+
echo "FAIL test1c"
5353
status=1
5454
fi
5555
rm -rf libgo.a libgo.h testp pkg
5656

5757
case "$(go env GOOS)/$(go env GOARCH)" in
5858
"darwin/arm" | "darwin/arm64")
59-
echo "Skipping test4; see https://golang.org/issue/13701"
59+
echo "Skipping test2; see https://golang.org/issue/13701"
6060
;;
6161
*)
6262
GOPATH=$(pwd) go build -buildmode=c-archive -o libgo2.a libgo2
6363
$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main2.c libgo2.a
6464
if ! $bin; then
65-
echo "FAIL test4"
65+
echo "FAIL test2"
6666
status=1
6767
fi
6868
rm -rf libgo2.a libgo2.h testp pkg
6969
;;
7070
esac
7171

72+
GOPATH=$(pwd) go build -buildmode=c-archive -o libgo3.a libgo3
73+
$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main3.c libgo3.a
74+
if ! $bin; then
75+
echo "FAIL test3"
76+
status=1
77+
fi
78+
rm -rf libgo3.a libgo3.h testp pkg
79+
7280
exit $status

0 commit comments

Comments
 (0)