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