1 // Copyright 2020 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 package main 9 10 // This is for issue #42207. 11 // During a call to needm we could get a SIGCHLD signal 12 // which would itself call needm, causing a deadlock. 13 14 /* 15 #include <signal.h> 16 #include <pthread.h> 17 #include <sched.h> 18 #include <unistd.h> 19 20 extern void GoNeedM(); 21 22 #define SIGNALERS 10 23 24 static void* needmSignalThread(void* p) { 25 pthread_t* pt = (pthread_t*)(p); 26 int i; 27 28 for (i = 0; i < 100; i++) { 29 if (pthread_kill(*pt, SIGCHLD) < 0) { 30 return NULL; 31 } 32 usleep(1); 33 } 34 return NULL; 35 } 36 37 // We don't need many calls, as the deadlock is only likely 38 // to occur the first couple of times that needm is called. 39 // After that there will likely be an extra M available. 40 #define CALLS 10 41 42 static void* needmCallbackThread(void* p) { 43 int i; 44 45 for (i = 0; i < SIGNALERS; i++) { 46 sched_yield(); // Help the signal threads get started. 47 } 48 for (i = 0; i < CALLS; i++) { 49 GoNeedM(); 50 } 51 return NULL; 52 } 53 54 static void runNeedmSignalThread() { 55 int i; 56 pthread_t caller; 57 pthread_t s[SIGNALERS]; 58 59 pthread_create(&caller, NULL, needmCallbackThread, NULL); 60 for (i = 0; i < SIGNALERS; i++) { 61 pthread_create(&s[i], NULL, needmSignalThread, &caller); 62 } 63 for (i = 0; i < SIGNALERS; i++) { 64 pthread_join(s[i], NULL); 65 } 66 pthread_join(caller, NULL); 67 } 68 */ 69 import "C" 70 71 import ( 72 "fmt" 73 "os" 74 "time" 75 ) 76 77 func init() { 78 register("NeedmDeadlock", NeedmDeadlock) 79 } 80 81 //export GoNeedM 82 func GoNeedM() { 83 } 84 85 func NeedmDeadlock() { 86 // The failure symptom is that the program hangs because of a 87 // deadlock in needm, so set an alarm. 88 go func() { 89 time.Sleep(5 * time.Second) 90 fmt.Println("Hung for 5 seconds") 91 os.Exit(1) 92 }() 93 94 C.runNeedmSignalThread() 95 fmt.Println("OK") 96 } 97