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 //go:build unix 6 7 package main 8 9 import ( 10 "fmt" 11 "os" 12 ) 13 14 /* 15 #include <signal.h> 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 sig_atomic_t expectCSigsegv; 21 int *sigfwdP; 22 23 static void sigsegv() { 24 expectCSigsegv = 1; 25 *sigfwdP = 1; 26 fprintf(stderr, "ERROR: C SIGSEGV not thrown on caught?.\n"); 27 exit(2); 28 } 29 30 static void segvhandler(int signum) { 31 if (signum == SIGSEGV) { 32 if (expectCSigsegv == 0) { 33 fprintf(stderr, "SIGSEGV caught in C unexpectedly\n"); 34 exit(1); 35 } 36 fprintf(stdout, "OK\n"); 37 exit(0); // success 38 } 39 } 40 41 static void __attribute__ ((constructor)) sigsetup(void) { 42 if (getenv("GO_TEST_CGOSIGFWD") == NULL) { 43 return; 44 } 45 46 struct sigaction act; 47 48 memset(&act, 0, sizeof act); 49 act.sa_handler = segvhandler; 50 sigaction(SIGSEGV, &act, NULL); 51 } 52 */ 53 import "C" 54 55 func init() { 56 register("CgoSigfwd", CgoSigfwd) 57 } 58 59 var nilPtr *byte 60 61 func f() (ret bool) { 62 defer func() { 63 if recover() == nil { 64 fmt.Fprintf(os.Stderr, "ERROR: couldn't raise SIGSEGV in Go\n") 65 C.exit(2) 66 } 67 ret = true 68 }() 69 *nilPtr = 1 70 return false 71 } 72 73 func CgoSigfwd() { 74 if os.Getenv("GO_TEST_CGOSIGFWD") == "" { 75 fmt.Fprintf(os.Stderr, "test must be run with GO_TEST_CGOSIGFWD set\n") 76 os.Exit(1) 77 } 78 79 // Test that the signal originating in Go is handled (and recovered) by Go. 80 if !f() { 81 fmt.Fprintf(os.Stderr, "couldn't recover from SIGSEGV in Go.\n") 82 C.exit(2) 83 } 84 85 // Test that the signal originating in C is handled by C. 86 C.sigsegv() 87 } 88