Text file misc/cgo/testcshared/testdata/main5.c

     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  }
   200  

View as plain text