github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/misc/cgo/testcshared/main5.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 that a signal handler works in non-Go code when using 6 // os/signal.Notify. 7 // This is a lot like misc/cgo/testcarchive/main3.c. 8 9 #include <signal.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <time.h> 14 #include <sched.h> 15 #include <dlfcn.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 int main(int argc, char** argv) { 29 int verbose; 30 struct sigaction sa; 31 void* handle; 32 void (*fn1)(void); 33 int (*sawSIGIO)(void); 34 int i; 35 struct timespec ts; 36 37 verbose = argc > 2; 38 setvbuf(stdout, NULL, _IONBF, 0); 39 40 if (verbose) { 41 printf("calling sigaction\n"); 42 } 43 44 memset(&sa, 0, sizeof sa); 45 sa.sa_sigaction = ioHandler; 46 if (sigemptyset(&sa.sa_mask) < 0) { 47 die("sigemptyset"); 48 } 49 sa.sa_flags = SA_SIGINFO; 50 if (sigaction(SIGIO, &sa, NULL) < 0) { 51 die("sigaction"); 52 } 53 54 if (verbose) { 55 printf("calling dlopen\n"); 56 } 57 58 handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); 59 if (handle == NULL) { 60 fprintf(stderr, "%s\n", dlerror()); 61 exit(EXIT_FAILURE); 62 } 63 64 // At this point there should not be a Go signal handler 65 // installed for SIGIO. 66 67 if (verbose) { 68 printf("raising SIGIO\n"); 69 } 70 71 if (raise(SIGIO) < 0) { 72 die("raise"); 73 } 74 75 if (verbose) { 76 printf("waiting for sigioSeen\n"); 77 } 78 79 // Wait until the signal has been delivered. 80 i = 0; 81 while (!sigioSeen) { 82 ts.tv_sec = 0; 83 ts.tv_nsec = 1000000; 84 nanosleep(&ts, NULL); 85 i++; 86 if (i > 5000) { 87 fprintf(stderr, "looping too long waiting for signal\n"); 88 exit(EXIT_FAILURE); 89 } 90 } 91 92 sigioSeen = 0; 93 94 // Tell the Go code to catch SIGIO. 95 96 if (verbose) { 97 printf("calling dlsym\n"); 98 } 99 100 fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO"); 101 if (fn1 == NULL) { 102 fprintf(stderr, "%s\n", dlerror()); 103 exit(EXIT_FAILURE); 104 } 105 106 if (verbose) { 107 printf("calling CatchSIGIO\n"); 108 } 109 110 fn1(); 111 112 if (verbose) { 113 printf("raising SIGIO\n"); 114 } 115 116 if (raise(SIGIO) < 0) { 117 die("raise"); 118 } 119 120 if (verbose) { 121 printf("calling dlsym\n"); 122 } 123 124 // Check that the Go code saw SIGIO. 125 sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO"); 126 if (sawSIGIO == NULL) { 127 fprintf(stderr, "%s\n", dlerror()); 128 exit(EXIT_FAILURE); 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 dlsym\n"); 149 } 150 151 fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO"); 152 if (fn1 == NULL) { 153 fprintf(stderr, "%s\n", dlerror()); 154 exit(EXIT_FAILURE); 155 } 156 157 if (verbose) { 158 printf("calling ResetSIGIO\n"); 159 } 160 161 fn1(); 162 163 if (verbose) { 164 printf("raising SIGIO\n"); 165 } 166 167 if (raise(SIGIO) < 0) { 168 die("raise"); 169 } 170 171 if (verbose) { 172 printf("calling SawSIGIO\n"); 173 } 174 175 if (sawSIGIO()) { 176 fprintf(stderr, "Go handler saw SIGIO after Reset\n"); 177 exit(EXIT_FAILURE); 178 } 179 180 if (verbose) { 181 printf("waiting for sigioSeen\n"); 182 } 183 184 // Wait until the signal has been delivered. 185 i = 0; 186 while (!sigioSeen) { 187 ts.tv_sec = 0; 188 ts.tv_nsec = 1000000; 189 nanosleep(&ts, NULL); 190 i++; 191 if (i > 5000) { 192 fprintf(stderr, "looping too long waiting for signal\n"); 193 exit(EXIT_FAILURE); 194 } 195 } 196 197 printf("PASS\n"); 198 return 0; 199 }