github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/misc/cgo/testcarchive/testdata/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 #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 }