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 !windows && !android 6 7 // Test that the Go runtime still works if C code changes the signal stack. 8 9 package cgotest 10 11 /* 12 #include <signal.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #ifdef _AIX 18 // On AIX, SIGSTKSZ is too small to handle Go sighandler. 19 #define CSIGSTKSZ 0x4000 20 #else 21 #define CSIGSTKSZ SIGSTKSZ 22 #endif 23 24 static stack_t oss; 25 static char signalStack[CSIGSTKSZ]; 26 27 static void changeSignalStack(void) { 28 stack_t ss; 29 memset(&ss, 0, sizeof ss); 30 ss.ss_sp = signalStack; 31 ss.ss_flags = 0; 32 ss.ss_size = CSIGSTKSZ; 33 if (sigaltstack(&ss, &oss) < 0) { 34 perror("sigaltstack"); 35 abort(); 36 } 37 } 38 39 static void restoreSignalStack(void) { 40 #if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__) 41 // The Darwin C library enforces a minimum that the kernel does not. 42 // This is OK since we allocated this much space in mpreinit, 43 // it was just removed from the buffer by stackalloc. 44 oss.ss_size = MINSIGSTKSZ; 45 #endif 46 if (sigaltstack(&oss, NULL) < 0) { 47 perror("sigaltstack restore"); 48 abort(); 49 } 50 } 51 52 static int zero(void) { 53 return 0; 54 } 55 */ 56 import "C" 57 58 import ( 59 "runtime" 60 "testing" 61 ) 62 63 func testSigaltstack(t *testing.T) { 64 switch { 65 case runtime.GOOS == "solaris", runtime.GOOS == "illumos", runtime.GOOS == "ios" && runtime.GOARCH == "arm64": 66 t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 67 } 68 69 C.changeSignalStack() 70 defer C.restoreSignalStack() 71 defer func() { 72 if recover() == nil { 73 t.Error("did not see expected panic") 74 } 75 }() 76 v := 1 / int(C.zero()) 77 t.Errorf("unexpected success of division by zero == %d", v) 78 } 79