github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/runtime/testdata/testprogcgo/racesig.go (about) 1 // Copyright 2016 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 // +build linux,amd64 6 7 package main 8 9 // Test that an external C thread that is calling malloc can be hit 10 // with SIGCHLD signals. This used to fail when built with the race 11 // detector, because in that case the signal handler would indirectly 12 // call the C malloc function. 13 14 /* 15 #include <errno.h> 16 #include <signal.h> 17 #include <stdint.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <pthread.h> 21 #include <sched.h> 22 #include <unistd.h> 23 24 #define ALLOCERS 100 25 #define SIGNALERS 10 26 27 static void* signalThread(void* p) { 28 pthread_t* pt = (pthread_t*)(p); 29 int i, j; 30 31 for (i = 0; i < 100; i++) { 32 for (j = 0; j < ALLOCERS; j++) { 33 if (pthread_kill(pt[j], SIGCHLD) < 0) { 34 return NULL; 35 } 36 } 37 usleep(1); 38 } 39 return NULL; 40 } 41 42 #define CALLS 100 43 44 static void* mallocThread(void* p) { 45 int i; 46 void *a[CALLS]; 47 48 for (i = 0; i < ALLOCERS; i++) { 49 sched_yield(); 50 } 51 for (i = 0; i < CALLS; i++) { 52 a[i] = malloc(i); 53 } 54 for (i = 0; i < CALLS; i++) { 55 free(a[i]); 56 } 57 return NULL; 58 } 59 60 void runRaceSignalThread() { 61 int i; 62 pthread_t m[ALLOCERS]; 63 pthread_t s[SIGNALERS]; 64 65 for (i = 0; i < ALLOCERS; i++) { 66 pthread_create(&m[i], NULL, mallocThread, NULL); 67 } 68 for (i = 0; i < SIGNALERS; i++) { 69 pthread_create(&s[i], NULL, signalThread, &m[0]); 70 } 71 for (i = 0; i < SIGNALERS; i++) { 72 pthread_join(s[i], NULL); 73 } 74 for (i = 0; i < ALLOCERS; i++) { 75 pthread_join(m[i], NULL); 76 } 77 } 78 */ 79 import "C" 80 81 import ( 82 "fmt" 83 "os" 84 "time" 85 ) 86 87 func init() { 88 register("CgoRaceSignal", CgoRaceSignal) 89 } 90 91 func CgoRaceSignal() { 92 // The failure symptom is that the program hangs because of a 93 // deadlock in malloc, so set an alarm. 94 go func() { 95 time.Sleep(5 * time.Second) 96 fmt.Println("Hung for 5 seconds") 97 os.Exit(1) 98 }() 99 100 C.runRaceSignalThread() 101 fmt.Println("OK") 102 }