1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
// Copyright 2017 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.
//go:build !plan9 && !windows
// +build !plan9,!windows
// Test handling of Go-allocated signal stacks when calling from
// C-created threads with and without signal stacks. (See issue
// #22930.)
package main
/*
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifdef _AIX
// On AIX, SIGSTKSZ is too small to handle Go sighandler.
#define CSIGSTKSZ 0x4000
#else
#define CSIGSTKSZ SIGSTKSZ
#endif
extern void SigStackCallback();
static void* WithSigStack(void* arg __attribute__((unused))) {
// Set up an alternate system stack.
void* base = mmap(0, CSIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if (base == MAP_FAILED) {
perror("mmap failed");
abort();
}
stack_t st = {}, ost = {};
st.ss_sp = (char*)base;
st.ss_flags = 0;
st.ss_size = CSIGSTKSZ;
if (sigaltstack(&st, &ost) < 0) {
perror("sigaltstack failed");
abort();
}
// Call Go.
SigStackCallback();
// Disable signal stack and protect it so we can detect reuse.
if (ost.ss_flags & SS_DISABLE) {
// Darwin libsystem has a bug where it checks ss_size
// even if SS_DISABLE is set. (The kernel gets it right.)
ost.ss_size = CSIGSTKSZ;
}
if (sigaltstack(&ost, NULL) < 0) {
perror("sigaltstack restore failed");
abort();
}
mprotect(base, CSIGSTKSZ, PROT_NONE);
return NULL;
}
static void* WithoutSigStack(void* arg __attribute__((unused))) {
SigStackCallback();
return NULL;
}
static void DoThread(int sigstack) {
pthread_t tid;
if (sigstack) {
pthread_create(&tid, NULL, WithSigStack, NULL);
} else {
pthread_create(&tid, NULL, WithoutSigStack, NULL);
}
pthread_join(tid, NULL);
}
*/
import "C"
func init() {
register("SigStack", SigStack)
}
func SigStack() {
C.DoThread(0)
C.DoThread(1)
C.DoThread(0)
C.DoThread(1)
println("OK")
}
var BadPtr *int
//export SigStackCallback
func SigStackCallback() {
// Cause the Go signal handler to run.
defer func() { recover() }()
*BadPtr = 42
}
|