github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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 <sched.h> 14 #include <dlfcn.h> 15 16 static void die(const char* msg) { 17 perror(msg); 18 exit(EXIT_FAILURE); 19 } 20 21 static volatile sig_atomic_t sigioSeen; 22 23 static void ioHandler(int signo, siginfo_t* info, void* ctxt) { 24 sigioSeen = 1; 25 } 26 27 int main(int argc, char** argv) { 28 int verbose; 29 struct sigaction sa; 30 void* handle; 31 void (*fn1)(void); 32 int (*sawSIGIO)(void); 33 int i; 34 35 verbose = argc > 2; 36 setvbuf(stdout, NULL, _IONBF, 0); 37 38 if (verbose) { 39 printf("calling sigaction\n"); 40 } 41 42 memset(&sa, 0, sizeof sa); 43 sa.sa_sigaction = ioHandler; 44 if (sigemptyset(&sa.sa_mask) < 0) { 45 die("sigemptyset"); 46 } 47 sa.sa_flags = SA_SIGINFO; 48 if (sigaction(SIGIO, &sa, NULL) < 0) { 49 die("sigaction"); 50 } 51 52 if (verbose) { 53 printf("calling dlopen\n"); 54 } 55 56 handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); 57 if (handle == NULL) { 58 fprintf(stderr, "%s\n", dlerror()); 59 exit(EXIT_FAILURE); 60 } 61 62 // At this point there should not be a Go signal handler 63 // installed for SIGIO. 64 65 if (verbose) { 66 printf("raising SIGIO\n"); 67 } 68 69 if (raise(SIGIO) < 0) { 70 die("raise"); 71 } 72 73 if (verbose) { 74 printf("waiting for sigioSeen\n"); 75 } 76 77 // Wait until the signal has been delivered. 78 i = 0; 79 while (!sigioSeen) { 80 if (sched_yield() < 0) { 81 perror("sched_yield"); 82 } 83 i++; 84 if (i > 100000) { 85 fprintf(stderr, "looping too long waiting for signal\n"); 86 exit(EXIT_FAILURE); 87 } 88 } 89 90 sigioSeen = 0; 91 92 // Tell the Go code to catch SIGIO. 93 94 if (verbose) { 95 printf("calling dlsym\n"); 96 } 97 98 fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO"); 99 if (fn1 == NULL) { 100 fprintf(stderr, "%s\n", dlerror()); 101 exit(EXIT_FAILURE); 102 } 103 104 if (verbose) { 105 printf("calling CatchSIGIO\n"); 106 } 107 108 fn1(); 109 110 if (verbose) { 111 printf("raising SIGIO\n"); 112 } 113 114 if (raise(SIGIO) < 0) { 115 die("raise"); 116 } 117 118 if (verbose) { 119 printf("calling dlsym\n"); 120 } 121 122 // Check that the Go code saw SIGIO. 123 sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO"); 124 if (sawSIGIO == NULL) { 125 fprintf(stderr, "%s\n", dlerror()); 126 exit(EXIT_FAILURE); 127 } 128 129 if (verbose) { 130 printf("calling SawSIGIO\n"); 131 } 132 133 if (!sawSIGIO()) { 134 fprintf(stderr, "Go handler did not see SIGIO\n"); 135 exit(EXIT_FAILURE); 136 } 137 138 if (sigioSeen != 0) { 139 fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n"); 140 exit(EXIT_FAILURE); 141 } 142 143 // Tell the Go code to stop catching SIGIO. 144 145 if (verbose) { 146 printf("calling dlsym\n"); 147 } 148 149 fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO"); 150 if (fn1 == NULL) { 151 fprintf(stderr, "%s\n", dlerror()); 152 exit(EXIT_FAILURE); 153 } 154 155 if (verbose) { 156 printf("calling ResetSIGIO\n"); 157 } 158 159 fn1(); 160 161 if (verbose) { 162 printf("raising SIGIO\n"); 163 } 164 165 if (raise(SIGIO) < 0) { 166 die("raise"); 167 } 168 169 if (verbose) { 170 printf("calling SawSIGIO\n"); 171 } 172 173 if (sawSIGIO()) { 174 fprintf(stderr, "Go handler saw SIGIO after Reset\n"); 175 exit(EXIT_FAILURE); 176 } 177 178 if (verbose) { 179 printf("waiting for sigioSeen\n"); 180 } 181 182 // Wait until the signal has been delivered. 183 i = 0; 184 while (!sigioSeen) { 185 if (sched_yield() < 0) { 186 perror("sched_yield"); 187 } 188 i++; 189 if (i > 100000) { 190 fprintf(stderr, "looping too long waiting for signal\n"); 191 exit(EXIT_FAILURE); 192 } 193 } 194 195 printf("PASS\n"); 196 return 0; 197 }