github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/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  
    15  #include "libgo3.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  // Set up the SIGPIPE signal handler in a high priority constructor, so
    29  // that it is installed before the Go code starts.
    30  
    31  static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
    32  	const char *s = "unexpected SIGPIPE\n";
    33  	write(2, s, strlen(s));
    34  	exit(EXIT_FAILURE);
    35  }
    36  
    37  static void init(void) __attribute__ ((constructor (200)));
    38  
    39  static void init() {
    40      struct sigaction sa;
    41  
    42  	memset(&sa, 0, sizeof sa);
    43  	sa.sa_sigaction = pipeHandler;
    44  	if (sigemptyset(&sa.sa_mask) < 0) {
    45  		die("sigemptyset");
    46  	}
    47  	sa.sa_flags = SA_SIGINFO;
    48  	if (sigaction(SIGPIPE, &sa, NULL) < 0) {
    49  		die("sigaction");
    50  	}
    51  }
    52  
    53  int main(int argc, char** argv) {
    54  	int verbose;
    55  	struct sigaction sa;
    56  	int i;
    57  	struct timespec ts;
    58  
    59  	verbose = argc > 2;
    60  	setvbuf(stdout, NULL, _IONBF, 0);
    61  
    62  	if (verbose) {
    63  		printf("raising SIGPIPE\n");
    64  	}
    65  
    66  	// Test that the Go runtime handles SIGPIPE, even if we installed
    67  	// a non-default SIGPIPE handler before the runtime initializes.
    68  	ProvokeSIGPIPE();
    69  
    70  	if (verbose) {
    71  		printf("calling sigaction\n");
    72  	}
    73  
    74  	memset(&sa, 0, sizeof sa);
    75  	sa.sa_sigaction = ioHandler;
    76  	if (sigemptyset(&sa.sa_mask) < 0) {
    77  		die("sigemptyset");
    78  	}
    79  	sa.sa_flags = SA_SIGINFO;
    80  	if (sigaction(SIGIO, &sa, NULL) < 0) {
    81  		die("sigaction");
    82  	}
    83  
    84  	// At this point there should not be a Go signal handler
    85  	// installed for SIGIO.
    86  
    87  	if (verbose) {
    88  		printf("raising SIGIO\n");
    89  	}
    90  
    91  	if (raise(SIGIO) < 0) {
    92  		die("raise");
    93  	}
    94  
    95  	if (verbose) {
    96  		printf("waiting for sigioSeen\n");
    97  	}
    98  
    99  	// Wait until the signal has been delivered.
   100  	i = 0;
   101  	while (!sigioSeen) {
   102  		ts.tv_sec = 0;
   103  		ts.tv_nsec = 1000000;
   104  		nanosleep(&ts, NULL);
   105  		i++;
   106  		if (i > 5000) {
   107  			fprintf(stderr, "looping too long waiting for signal\n");
   108  			exit(EXIT_FAILURE);
   109  		}
   110  	}
   111  
   112  	sigioSeen = 0;
   113  
   114  	// Tell the Go code to catch SIGIO.
   115  
   116  	if (verbose) {
   117  		printf("calling CatchSIGIO\n");
   118  	}
   119  
   120  	CatchSIGIO();
   121  
   122  	if (verbose) {
   123  		printf("raising SIGIO\n");
   124  	}
   125  
   126  	if (raise(SIGIO) < 0) {
   127  		die("raise");
   128  	}
   129  
   130  	if (verbose) {
   131  		printf("calling SawSIGIO\n");
   132  	}
   133  
   134  	if (!SawSIGIO()) {
   135  		fprintf(stderr, "Go handler did not see SIGIO\n");
   136  		exit(EXIT_FAILURE);
   137  	}
   138  
   139  	if (sigioSeen != 0) {
   140  		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
   141  		exit(EXIT_FAILURE);
   142  	}
   143  
   144  	// Tell the Go code to stop catching SIGIO.
   145  
   146  	if (verbose) {
   147  		printf("calling ResetSIGIO\n");
   148  	}
   149  
   150  	ResetSIGIO();
   151  
   152  	if (verbose) {
   153  		printf("raising SIGIO\n");
   154  	}
   155  
   156  	if (raise(SIGIO) < 0) {
   157  		die("raise");
   158  	}
   159  
   160  	if (verbose) {
   161  		printf("calling SawSIGIO\n");
   162  	}
   163  
   164  	if (SawSIGIO()) {
   165  		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
   166  		exit(EXIT_FAILURE);
   167  	}
   168  
   169  	if (verbose) {
   170  		printf("waiting for sigioSeen\n");
   171  	}
   172  
   173  	// Wait until the signal has been delivered.
   174  	i = 0;
   175  	while (!sigioSeen) {
   176  		ts.tv_sec = 0;
   177  		ts.tv_nsec = 1000000;
   178  		nanosleep(&ts, NULL);
   179  		i++;
   180  		if (i > 5000) {
   181  			fprintf(stderr, "looping too long waiting for signal\n");
   182  			exit(EXIT_FAILURE);
   183  		}
   184  	}
   185  
   186  	printf("PASS\n");
   187  	return 0;
   188  }