github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/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 extern void SigStackCallback(); 21 22 static void* WithSigStack(void* arg __attribute__((unused))) { 23 // Set up an alternate system stack. 24 void* base = mmap(0, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 25 if (base == MAP_FAILED) { 26 perror("mmap failed"); 27 abort(); 28 } 29 stack_t st = {}, ost = {}; 30 st.ss_sp = (char*)base; 31 st.ss_flags = 0; 32 st.ss_size = SIGSTKSZ; 33 if (sigaltstack(&st, &ost) < 0) { 34 perror("sigaltstack failed"); 35 abort(); 36 } 37 38 // Call Go. 39 SigStackCallback(); 40 41 // Disable signal stack and protect it so we can detect reuse. 42 if (ost.ss_flags & SS_DISABLE) { 43 // Darwin libsystem has a bug where it checks ss_size 44 // even if SS_DISABLE is set. (The kernel gets it right.) 45 ost.ss_size = SIGSTKSZ; 46 } 47 if (sigaltstack(&ost, NULL) < 0) { 48 perror("sigaltstack restore failed"); 49 abort(); 50 } 51 mprotect(base, SIGSTKSZ, PROT_NONE); 52 return NULL; 53 } 54 55 static void* WithoutSigStack(void* arg __attribute__((unused))) { 56 SigStackCallback(); 57 return NULL; 58 } 59 60 static void DoThread(int sigstack) { 61 pthread_t tid; 62 if (sigstack) { 63 pthread_create(&tid, NULL, WithSigStack, NULL); 64 } else { 65 pthread_create(&tid, NULL, WithoutSigStack, NULL); 66 } 67 pthread_join(tid, NULL); 68 } 69 */ 70 import "C" 71 72 func init() { 73 register("SigStack", SigStack) 74 } 75 76 func SigStack() { 77 C.DoThread(0) 78 C.DoThread(1) 79 C.DoThread(0) 80 C.DoThread(1) 81 println("OK") 82 } 83 84 var BadPtr *int 85 86 //export SigStackCallback 87 func SigStackCallback() { 88 // Cause the Go signal handler to run. 89 defer func() { recover() }() 90 *BadPtr = 42 91 }