github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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  }
    54  
    55  static void sigioOnThread() {
    56  	pthread_t tid;
    57  	int i;
    58  
    59  	pthread_create(&tid, NULL, sigioThread, NULL);
    60  	pthread_join(tid, NULL);
    61  
    62  	// Wait until the signal has been delivered.
    63  	i = 0;
    64  	while (!sigioSeen) {
    65  		if (sched_yield() < 0) {
    66  			perror("sched_yield");
    67  		}
    68  		i++;
    69  		if (i > 10000) {
    70  			fprintf(stderr, "looping too long waiting for signal\n");
    71  			exit(EXIT_FAILURE);
    72  		}
    73  	}
    74  }
    75  
    76  static void __attribute__ ((constructor)) sigsetup(void) {
    77  	struct sigaction act;
    78  
    79  	memset(&act, 0, sizeof act);
    80  	act.sa_handler = segvhandler;
    81  	sigaction(SIGSEGV, &act, NULL);
    82  
    83  	act.sa_handler = iohandler;
    84  	sigaction(SIGIO, &act, NULL);
    85  }
    86  */
    87  import "C"
    88  
    89  var p *byte
    90  
    91  func f() (ret bool) {
    92  	defer func() {
    93  		if recover() == nil {
    94  			fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.")
    95  			C.exit(2)
    96  		}
    97  		ret = true
    98  	}()
    99  	*p = 1
   100  	return false
   101  }
   102  
   103  func main() {
   104  	// Test that the signal originating in Go is handled (and recovered) by Go.
   105  	if !f() {
   106  		fmt.Errorf("couldn't recover from SIGSEGV in Go.")
   107  		C.exit(2)
   108  	}
   109  
   110  	// Test that the signal originating in C is handled by C.
   111  	C.sigsegv()
   112  }