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 <time.h>
13#include <sched.h>
14
15#include "libgo3.h"
16
17static void die(const char* msg) {
18	perror(msg);
19	exit(EXIT_FAILURE);
20}
21
22static volatile sig_atomic_t sigioSeen;
23
24static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
25	sigioSeen = 1;
26}
27
28int main(int argc, char** argv) {
29	int verbose;
30	struct sigaction sa;
31	int i;
32	struct timespec ts;
33
34	verbose = argc > 2;
35	setvbuf(stdout, NULL, _IONBF, 0);
36
37	if (verbose) {
38		printf("calling sigaction\n");
39	}
40
41	memset(&sa, 0, sizeof sa);
42	sa.sa_sigaction = ioHandler;
43	if (sigemptyset(&sa.sa_mask) < 0) {
44		die("sigemptyset");
45	}
46	sa.sa_flags = SA_SIGINFO;
47	if (sigaction(SIGIO, &sa, NULL) < 0) {
48		die("sigaction");
49	}
50
51	// At this point there should not be a Go signal handler
52	// installed for SIGIO.
53
54	if (verbose) {
55		printf("raising SIGIO\n");
56	}
57
58	if (raise(SIGIO) < 0) {
59		die("raise");
60	}
61
62	if (verbose) {
63		printf("waiting for sigioSeen\n");
64	}
65
66	// Wait until the signal has been delivered.
67	i = 0;
68	while (!sigioSeen) {
69		ts.tv_sec = 0;
70		ts.tv_nsec = 1000000;
71		nanosleep(&ts, NULL);
72		i++;
73		if (i > 5000) {
74			fprintf(stderr, "looping too long waiting for signal\n");
75			exit(EXIT_FAILURE);
76		}
77	}
78
79	sigioSeen = 0;
80
81	// Tell the Go code to catch SIGIO.
82
83	if (verbose) {
84		printf("calling CatchSIGIO\n");
85	}
86
87	CatchSIGIO();
88
89	if (verbose) {
90		printf("raising SIGIO\n");
91	}
92
93	if (raise(SIGIO) < 0) {
94		die("raise");
95	}
96
97	if (verbose) {
98		printf("calling SawSIGIO\n");
99	}
100
101	if (!SawSIGIO()) {
102		fprintf(stderr, "Go handler did not see SIGIO\n");
103		exit(EXIT_FAILURE);
104	}
105
106	if (sigioSeen != 0) {
107		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
108		exit(EXIT_FAILURE);
109	}
110
111	// Tell the Go code to stop catching SIGIO.
112
113	if (verbose) {
114		printf("calling ResetSIGIO\n");
115	}
116
117	ResetSIGIO();
118
119	if (verbose) {
120		printf("raising SIGIO\n");
121	}
122
123	if (raise(SIGIO) < 0) {
124		die("raise");
125	}
126
127	if (verbose) {
128		printf("calling SawSIGIO\n");
129	}
130
131	if (SawSIGIO()) {
132		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
133		exit(EXIT_FAILURE);
134	}
135
136	if (verbose) {
137		printf("waiting for sigioSeen\n");
138	}
139
140	// Wait until the signal has been delivered.
141	i = 0;
142	while (!sigioSeen) {
143		ts.tv_sec = 0;
144		ts.tv_nsec = 1000000;
145		nanosleep(&ts, NULL);
146		i++;
147		if (i > 5000) {
148			fprintf(stderr, "looping too long waiting for signal\n");
149			exit(EXIT_FAILURE);
150		}
151	}
152
153	printf("PASS\n");
154	return 0;
155}
156