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