github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/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  }