Home | History | Annotate | Download | only in testprogcgo
      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 }
     92