github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/runtime/testdata/testprogcgo/threadprof.go (about)

     1  // Copyright 2015 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  // We only build this file with the tag "threadprof", since it starts
     6  // a thread running a busy loop at constructor time.
     7  
     8  // +build !plan9,!windows
     9  // +build threadprof
    10  
    11  package main
    12  
    13  /*
    14  #include <stdint.h>
    15  #include <signal.h>
    16  #include <pthread.h>
    17  
    18  volatile int32_t spinlock;
    19  
    20  static void *thread1(void *p) {
    21  	(void)p;
    22  	while (spinlock == 0)
    23  		;
    24  	pthread_kill(pthread_self(), SIGPROF);
    25  	spinlock = 0;
    26  	return NULL;
    27  }
    28  
    29  __attribute__((constructor)) void issue9456() {
    30  	pthread_t tid;
    31  	pthread_create(&tid, 0, thread1, NULL);
    32  }
    33  
    34  void **nullptr;
    35  
    36  void *crash(void *p) {
    37  	*nullptr = p;
    38  	return 0;
    39  }
    40  
    41  int start_crashing_thread(void) {
    42  	pthread_t tid;
    43  	return pthread_create(&tid, 0, crash, 0);
    44  }
    45  */
    46  import "C"
    47  
    48  import (
    49  	"fmt"
    50  	"os"
    51  	"os/exec"
    52  	"runtime"
    53  	"sync/atomic"
    54  	"time"
    55  	"unsafe"
    56  )
    57  
    58  func init() {
    59  	register("CgoExternalThreadSIGPROF", CgoExternalThreadSIGPROF)
    60  	register("CgoExternalThreadSignal", CgoExternalThreadSignal)
    61  }
    62  
    63  func CgoExternalThreadSIGPROF() {
    64  	// This test intends to test that sending SIGPROF to foreign threads
    65  	// before we make any cgo call will not abort the whole process, so
    66  	// we cannot make any cgo call here. See https://golang.org/issue/9456.
    67  	atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
    68  	for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
    69  		runtime.Gosched()
    70  	}
    71  	println("OK")
    72  }
    73  
    74  func CgoExternalThreadSignal() {
    75  	if len(os.Args) > 2 && os.Args[2] == "crash" {
    76  		i := C.start_crashing_thread()
    77  		if i != 0 {
    78  			fmt.Println("pthread_create failed:", i)
    79  			// Exit with 0 because parent expects us to crash.
    80  			return
    81  		}
    82  
    83  		// We should crash immediately, but give it plenty of
    84  		// time before failing (by exiting 0) in case we are
    85  		// running on a slow system.
    86  		time.Sleep(5 * time.Second)
    87  		return
    88  	}
    89  
    90  	out, err := exec.Command(os.Args[0], "CgoExternalThreadSignal", "crash").CombinedOutput()
    91  	if err == nil {
    92  		fmt.Println("C signal did not crash as expected")
    93  		fmt.Printf("\n%s\n", out)
    94  		os.Exit(1)
    95  	}
    96  
    97  	fmt.Println("OK")
    98  }