Home | History | Annotate | Download | only in test
      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 // +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 static stack_t oss;
     18 static char signalStack[SIGSTKSZ];
     19 
     20 static void changeSignalStack(void) {
     21 	stack_t ss;
     22 	memset(&ss, 0, sizeof ss);
     23 	ss.ss_sp = signalStack;
     24 	ss.ss_flags = 0;
     25 	ss.ss_size = SIGSTKSZ;
     26 	if (sigaltstack(&ss, &oss) < 0) {
     27 		perror("sigaltstack");
     28 		abort();
     29 	}
     30 }
     31 
     32 static void restoreSignalStack(void) {
     33 #if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
     34 	// The Darwin C library enforces a minimum that the kernel does not.
     35 	// This is OK since we allocated this much space in mpreinit,
     36 	// it was just removed from the buffer by stackalloc.
     37 	oss.ss_size = MINSIGSTKSZ;
     38 #endif
     39 	if (sigaltstack(&oss, NULL) < 0) {
     40 		perror("sigaltstack restore");
     41 		abort();
     42 	}
     43 }
     44 
     45 static int zero(void) {
     46 	return 0;
     47 }
     48 */
     49 import "C"
     50 
     51 import (
     52 	"runtime"
     53 	"testing"
     54 )
     55 
     56 func testSigaltstack(t *testing.T) {
     57 	switch {
     58 	case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
     59 		t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
     60 	case runtime.GOOS == "darwin" && runtime.GOARCH == "386":
     61 		t.Skipf("sigaltstack fails on darwin/386")
     62 	}
     63 
     64 	C.changeSignalStack()
     65 	defer C.restoreSignalStack()
     66 	defer func() {
     67 		if recover() == nil {
     68 			t.Error("did not see expected panic")
     69 		}
     70 	}()
     71 	v := 1 / int(C.zero())
     72 	t.Errorf("unexpected success of division by zero == %d", v)
     73 }
     74