Source file src/runtime/testdata/testprogcgo/needmdeadlock.go
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 ) 74 75 func init() { 76 register("NeedmDeadlock", NeedmDeadlock) 77 } 78 79 //export GoNeedM 80 func GoNeedM() { 81 } 82 83 func NeedmDeadlock() { 84 // The failure symptom is that the program hangs because of a 85 // deadlock in needm. Instead of using an arbitrary timeout, 86 // we let the test deadline expire if it deadlocks. 87 88 C.runNeedmSignalThread() 89 fmt.Println("OK") 90 } 91