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