Source file misc/cgo/testsigfwd/main.go

     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  		fprintf(stdout, "ok\ttestsigfwd\n");
    29  		exit(0);  // success
    30  	}
    31  }
    32  
    33  static volatile sig_atomic_t sigioSeen;
    34  
    35  // Use up some stack space.
    36  static void recur(int i, char *p) {
    37  	char a[1024];
    38  
    39  	*p = '\0';
    40  	if (i > 0) {
    41  		recur(i - 1, a);
    42  	}
    43  }
    44  
    45  static void iohandler(int signum) {
    46  	char a[1024];
    47  
    48  	recur(4, a);
    49  	sigioSeen = 1;
    50  }
    51  
    52  static void* sigioThread(void* arg __attribute__ ((unused))) {
    53  	raise(SIGIO);
    54  	return NULL;
    55  }
    56  
    57  static void sigioOnThread() {
    58  	pthread_t tid;
    59  	int i;
    60  
    61  	pthread_create(&tid, NULL, sigioThread, NULL);
    62  	pthread_join(tid, NULL);
    63  
    64  	// Wait until the signal has been delivered.
    65  	i = 0;
    66  	while (!sigioSeen) {
    67  		if (sched_yield() < 0) {
    68  			perror("sched_yield");
    69  		}
    70  		i++;
    71  		if (i > 10000) {
    72  			fprintf(stderr, "looping too long waiting for signal\n");
    73  			exit(EXIT_FAILURE);
    74  		}
    75  	}
    76  }
    77  
    78  static void __attribute__ ((constructor)) sigsetup(void) {
    79  	struct sigaction act;
    80  
    81  	memset(&act, 0, sizeof act);
    82  	act.sa_handler = segvhandler;
    83  	sigaction(SIGSEGV, &act, NULL);
    84  
    85  	act.sa_handler = iohandler;
    86  	sigaction(SIGIO, &act, NULL);
    87  }
    88  */
    89  import "C"
    90  
    91  var p *byte
    92  
    93  func f() (ret bool) {
    94  	defer func() {
    95  		if recover() == nil {
    96  			fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.")
    97  			C.exit(2)
    98  		}
    99  		ret = true
   100  	}()
   101  	*p = 1
   102  	return false
   103  }
   104  
   105  func main() {
   106  	// Test that the signal originating in Go is handled (and recovered) by Go.
   107  	if !f() {
   108  		fmt.Errorf("couldn't recover from SIGSEGV in Go.")
   109  		C.exit(2)
   110  	}
   111  
   112  	// Test that the signal originating in C is handled by C.
   113  	C.sigsegv()
   114  }
   115  

View as plain text