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 18static void die(const char* msg) { 19 perror(msg); 20 exit(EXIT_FAILURE); 21} 22 23static volatile sig_atomic_t sigioSeen; 24 25static 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 32static 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 38static void init(void) __attribute__ ((constructor (200))); 39 40static 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 54int 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