]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/cgo/internal/testcarchive/testdata/main3.c
misc/cgo: move easy tests to cmd/cgo/internal
[gostls13.git] / src / cmd / cgo / internal / testcarchive / testdata / main3.c
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 ../testcshared/main5.c.
7
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <sched.h>
14 #include <unistd.h>
15 #include <pthread.h>
16
17 #include "libgo3.h"
18
19 static void die(const char* msg) {
20         perror(msg);
21         exit(EXIT_FAILURE);
22 }
23
24 static volatile sig_atomic_t sigioSeen;
25
26 static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
27         sigioSeen = 1;
28 }
29
30 // Set up the SIGPIPE signal handler in a high priority constructor, so
31 // that it is installed before the Go code starts.
32
33 static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
34         const char *s = "unexpected SIGPIPE\n";
35         write(2, s, strlen(s));
36         exit(EXIT_FAILURE);
37 }
38
39 static void init(void) __attribute__ ((constructor (200)));
40
41 static void init() {
42     struct sigaction sa;
43
44         memset(&sa, 0, sizeof sa);
45         sa.sa_sigaction = pipeHandler;
46         if (sigemptyset(&sa.sa_mask) < 0) {
47                 die("sigemptyset");
48         }
49         sa.sa_flags = SA_SIGINFO;
50         if (sigaction(SIGPIPE, &sa, NULL) < 0) {
51                 die("sigaction");
52         }
53 }
54
55 static void *provokeSIGPIPE(void *arg) {
56         ProvokeSIGPIPE();
57         return NULL;
58 }
59
60 int main(int argc, char** argv) {
61         int verbose;
62         struct sigaction sa;
63         int i;
64         struct timespec ts;
65         int res;
66         pthread_t tid;
67
68         verbose = argc > 2;
69         setvbuf(stdout, NULL, _IONBF, 0);
70
71         if (verbose) {
72                 printf("raising SIGPIPE\n");
73         }
74
75         // Test that the Go runtime handles SIGPIPE, even if we installed
76         // a non-default SIGPIPE handler before the runtime initializes.
77         ProvokeSIGPIPE();
78
79         // Test that SIGPIPE on a non-main thread is also handled by Go.
80         res = pthread_create(&tid, NULL, provokeSIGPIPE, NULL);
81         if (res != 0) {
82                 fprintf(stderr, "pthread_create: %s\n", strerror(res));
83                 exit(EXIT_FAILURE);
84         }
85
86         res = pthread_join(tid, NULL);
87         if (res != 0) {
88                 fprintf(stderr, "pthread_join: %s\n", strerror(res));
89                 exit(EXIT_FAILURE);
90         }
91
92         if (verbose) {
93                 printf("calling sigaction\n");
94         }
95
96         memset(&sa, 0, sizeof sa);
97         sa.sa_sigaction = ioHandler;
98         if (sigemptyset(&sa.sa_mask) < 0) {
99                 die("sigemptyset");
100         }
101         sa.sa_flags = SA_SIGINFO;
102         if (sigaction(SIGIO, &sa, NULL) < 0) {
103                 die("sigaction");
104         }
105
106         // At this point there should not be a Go signal handler
107         // installed for SIGIO.
108
109         if (verbose) {
110                 printf("raising SIGIO\n");
111         }
112
113         if (raise(SIGIO) < 0) {
114                 die("raise");
115         }
116
117         if (verbose) {
118                 printf("waiting for sigioSeen\n");
119         }
120
121         // Wait until the signal has been delivered.
122         i = 0;
123         while (!sigioSeen) {
124                 ts.tv_sec = 0;
125                 ts.tv_nsec = 1000000;
126                 nanosleep(&ts, NULL);
127                 i++;
128                 if (i > 5000) {
129                         fprintf(stderr, "looping too long waiting for signal\n");
130                         exit(EXIT_FAILURE);
131                 }
132         }
133
134         sigioSeen = 0;
135
136         // Tell the Go code to catch SIGIO.
137
138         if (verbose) {
139                 printf("calling CatchSIGIO\n");
140         }
141
142         CatchSIGIO();
143
144         if (verbose) {
145                 printf("raising SIGIO\n");
146         }
147
148         if (raise(SIGIO) < 0) {
149                 die("raise");
150         }
151
152         if (verbose) {
153                 printf("calling SawSIGIO\n");
154         }
155
156         if (!SawSIGIO()) {
157                 fprintf(stderr, "Go handler did not see SIGIO\n");
158                 exit(EXIT_FAILURE);
159         }
160
161         if (sigioSeen != 0) {
162                 fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
163                 exit(EXIT_FAILURE);
164         }
165
166         // Tell the Go code to stop catching SIGIO.
167
168         if (verbose) {
169                 printf("calling ResetSIGIO\n");
170         }
171
172         ResetSIGIO();
173
174         if (verbose) {
175                 printf("raising SIGIO\n");
176         }
177
178         if (raise(SIGIO) < 0) {
179                 die("raise");
180         }
181
182         if (verbose) {
183                 printf("calling SawSIGIO\n");
184         }
185
186         if (SawSIGIO()) {
187                 fprintf(stderr, "Go handler saw SIGIO after Reset\n");
188                 exit(EXIT_FAILURE);
189         }
190
191         if (verbose) {
192                 printf("waiting for sigioSeen\n");
193         }
194
195         // Wait until the signal has been delivered.
196         i = 0;
197         while (!sigioSeen) {
198                 ts.tv_sec = 0;
199                 ts.tv_nsec = 1000000;
200                 nanosleep(&ts, NULL);
201                 i++;
202                 if (i > 5000) {
203                         fprintf(stderr, "looping too long waiting for signal\n");
204                         exit(EXIT_FAILURE);
205                 }
206         }
207
208         printf("PASS\n");
209         return 0;
210 }