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