Source file src/runtime/testdata/testprogcgo/sigstack.go

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

View as plain text