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  }