github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/misc/cgo/testsigfwd/main.go (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  package main
     6  
     7  import "fmt"
     8  
     9  /*
    10  #cgo CFLAGS: -pthread
    11  #cgo LDFLAGS: -pthread
    12  
    13  #include <signal.h>
    14  #include <stdlib.h>
    15  #include <stdio.h>
    16  #include <string.h>
    17  #include <pthread.h>
    18  
    19  int *p;
    20  static void sigsegv() {
    21  	*p = 1;
    22  	fprintf(stderr, "ERROR: C SIGSEGV not thrown on caught?.\n");
    23  	exit(2);
    24  }
    25  
    26  static void segvhandler(int signum) {
    27  	if (signum == SIGSEGV) {
    28  		exit(0);  // success
    29  	}
    30  }
    31  
    32  static volatile sig_atomic_t sigioSeen;
    33  
    34  // Use up some stack space.
    35  static void recur(int i, char *p) {
    36  	char a[1024];
    37  
    38  	*p = '\0';
    39  	if (i > 0) {
    40  		recur(i - 1, a);
    41  	}
    42  }
    43  
    44  static void iohandler(int signum) {
    45  	char a[1024];
    46  
    47  	recur(4, a);
    48  	sigioSeen = 1;
    49  }
    50  
    51  static void* sigioThread(void* arg __attribute__ ((unused))) {
    52  	raise(SIGIO);
    53  	return NULL;
    54  }
    55  
    56  static void sigioOnThread() {
    57  	pthread_t tid;
    58  	int i;
    59  
    60  	pthread_create(&tid, NULL, sigioThread, NULL);
    61  	pthread_join(tid, NULL);
    62  
    63  	// Wait until the signal has been delivered.
    64  	i = 0;
    65  	while (!sigioSeen) {
    66  		if (sched_yield() < 0) {
    67  			perror("sched_yield");
    68  		}
    69  		i++;
    70  		if (i > 10000) {
    71  			fprintf(stderr, "looping too long waiting for signal\n");
    72  			exit(EXIT_FAILURE);
    73  		}
    74  	}
    75  }
    76  
    77  static void __attribute__ ((constructor)) sigsetup(void) {
    78  	struct sigaction act;
    79  
    80  	memset(&act, 0, sizeof act);
    81  	act.sa_handler = segvhandler;
    82  	sigaction(SIGSEGV, &act, NULL);
    83  
    84  	act.sa_handler = iohandler;
    85  	sigaction(SIGIO, &act, NULL);
    86  }
    87  */
    88  import "C"
    89  
    90  var p *byte
    91  
    92  func f() (ret bool) {
    93  	defer func() {
    94  		if recover() == nil {
    95  			fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.")
    96  			C.exit(2)
    97  		}
    98  		ret = true
    99  	}()
   100  	*p = 1
   101  	return false
   102  }
   103  
   104  func main() {
   105  	// Test that the signal originating in Go is handled (and recovered) by Go.
   106  	if !f() {
   107  		fmt.Errorf("couldn't recover from SIGSEGV in Go.")
   108  		C.exit(2)
   109  	}
   110  
   111  	// Test that the signal originating in C is handled by C.
   112  	C.sigsegv()
   113  }