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 } 99