Home | History | Annotate | Download | only in testprogcgo
      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 }
    103