2015-12-21 23:27:01 -07:00
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2016-06-01 12:58:02 -06:00
|
|
|
// +build !windows,!android
|
2015-12-21 23:27:01 -07:00
|
|
|
|
|
|
|
// Test that the Go runtime still works if C code changes the signal stack.
|
|
|
|
|
|
|
|
package cgotest
|
|
|
|
|
|
|
|
/*
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2020-03-03 08:24:32 -07:00
|
|
|
#ifdef _AIX
|
|
|
|
// On AIX, SIGSTKSZ is too small to handle Go sighandler.
|
|
|
|
#define CSIGSTKSZ 0x4000
|
|
|
|
#else
|
|
|
|
#define CSIGSTKSZ SIGSTKSZ
|
|
|
|
#endif
|
|
|
|
|
2015-12-21 23:27:01 -07:00
|
|
|
static stack_t oss;
|
2020-03-03 08:24:32 -07:00
|
|
|
static char signalStack[CSIGSTKSZ];
|
2015-12-21 23:27:01 -07:00
|
|
|
|
2017-01-19 23:04:45 -07:00
|
|
|
static void changeSignalStack(void) {
|
2015-12-21 23:27:01 -07:00
|
|
|
stack_t ss;
|
|
|
|
memset(&ss, 0, sizeof ss);
|
|
|
|
ss.ss_sp = signalStack;
|
|
|
|
ss.ss_flags = 0;
|
2020-03-03 08:24:32 -07:00
|
|
|
ss.ss_size = CSIGSTKSZ;
|
2015-12-21 23:27:01 -07:00
|
|
|
if (sigaltstack(&ss, &oss) < 0) {
|
|
|
|
perror("sigaltstack");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 23:04:45 -07:00
|
|
|
static void restoreSignalStack(void) {
|
2016-01-24 09:02:19 -07:00
|
|
|
#if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
|
2015-12-21 23:27:01 -07:00
|
|
|
// The Darwin C library enforces a minimum that the kernel does not.
|
|
|
|
// This is OK since we allocated this much space in mpreinit,
|
|
|
|
// it was just removed from the buffer by stackalloc.
|
|
|
|
oss.ss_size = MINSIGSTKSZ;
|
|
|
|
#endif
|
|
|
|
if (sigaltstack(&oss, NULL) < 0) {
|
|
|
|
perror("sigaltstack restore");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 23:04:45 -07:00
|
|
|
static int zero(void) {
|
2015-12-21 23:27:01 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
import "C"
|
|
|
|
|
|
|
|
import (
|
|
|
|
"runtime"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func testSigaltstack(t *testing.T) {
|
|
|
|
switch {
|
2020-04-03 10:22:27 -06:00
|
|
|
case runtime.GOOS == "solaris", runtime.GOOS == "illumos", runtime.GOOS == "darwin" && runtime.GOARCH == "arm64":
|
2015-12-24 11:26:02 -07:00
|
|
|
t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
2015-12-21 23:27:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
C.changeSignalStack()
|
|
|
|
defer C.restoreSignalStack()
|
|
|
|
defer func() {
|
|
|
|
if recover() == nil {
|
|
|
|
t.Error("did not see expected panic")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
v := 1 / int(C.zero())
|
|
|
|
t.Errorf("unexpected success of division by zero == %d", v)
|
|
|
|
}
|