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