github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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  #include <unistd.h>
    15  
    16  #include "libgo3.h"
    17  
    18  static void die(const char* msg) {
    19  	perror(msg);
    20  	exit(EXIT_FAILURE);
    21  }
    22  
    23  static volatile sig_atomic_t sigioSeen;
    24  
    25  static 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  
    32  static 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  
    38  static void init(void) __attribute__ ((constructor (200)));
    39  
    40  static 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  
    54  int 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  }