#include #include #include #include #include #include #include #include #define CALLOC_NMEMB 10000 /* * VERSION 1.1 * This testcase has 4 threads. The main thread simply starts the other threads * and then sleeps on a pthread_join. The forkingThread repeatedly calls * fork. The signalingThread repeatedly signals the forking thread, which * causes the forking thread to do sigsuspend. The third thread repeatedly * callocs and frees memory. Only when it is done with the calloc does it * signal the suspended thread to continue. The theory is that when the forking * thread gets suspended in the right place, it is holding a lock that the * callocing thread needs to continue, so the calloc thread hangs waiting on * that lock, and it cannot signal the forking thread to continue, creating a * deadlock. */ int killflag = 1; pthread_t forkThread; pthread_t sigThread; pthread_t calThread; void sigusr1Handler(int signum){ sigset_t set1; sigfillset(&set1); sigdelset(&set1, SIGUSR2); sigsuspend(&set1); killflag = 1; } void sigusr2Handler(int signum){ return; } void* callocingThread(void *ptr) { int * memptr; while(1) { memptr = calloc(CALLOC_NMEMB,4); if (!memptr){ fprintf(stderr, "calloc failed\n"); } pthread_kill(forkThread, SIGUSR2); free(memptr); } } void* signalingThread(void *ptr) { while(1) { if (killflag) { killflag = 0; pthread_kill(forkThread, SIGUSR1); } } } void* forkingThread(void *ptr) { pid_t pid; int i; struct sigaction sigusr1_action; struct sigaction sigusr2_action; sigfillset(&sigusr1_action.sa_mask); sigfillset(&sigusr2_action.sa_mask); sigusr1_action.sa_handler = &sigusr1Handler; sigusr2_action.sa_handler = &sigusr2Handler; sigaction(SIGUSR1, &sigusr1_action, NULL); sigaction(SIGUSR2, &sigusr2_action, NULL); while(1) { pid = fork(); fprintf(stderr, "."); if (pid == 0){ /* child */ exit(0); } else if (pid > 0) { /* parent */ waitpid(pid,NULL,NULL); continue; } else { fprintf(stderr, "fork failed\n"); } } } int main(int argc , char *argv[]) { pthread_create(&forkThread, 0, &forkingThread, 0); pthread_create(&calThread, 0, &callocingThread, 0); pthread_create(&sigThread, 0, &signalingThread, 0); pthread_join(forkThread, NULL); return 0; }