1 /* 2 This test makes sure the thread exit notification signals don't 3 interfere with the stack growth signals. 4 5 Thread death notifications are sent as RT signals, which are 6 queued. In general, these notifications are ignored, since they're 7 only used by the main thread if it has exited and is still waiting 8 for the rest to exit. 9 10 The system has a finite limit to the number of RT signals which can 11 be queued (typically 1024), and beyond that it stops queueing 12 siginfo. We rely on getting SIGSEGVs with siginfo information to 13 grow the stack. If we don't get the siginfo, then it just looks 14 like the program crashed. 15 16 The extra complication in this test is making sure that the 17 unwanted signals are discarded while the main thread is blocked in 18 a syscall. So, to check this, main creates a new process, which 19 attempts to grow the stack once all the threads have been created 20 and exited. main() itself is blocked waiting for the child 21 process. 22 23 Oh, and this test also makes sure that thread resources are cleaned 24 up properly. 25 */ 26 #include <pthread.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <signal.h> 32 #include <sys/wait.h> 33 34 static int grower; 35 36 static void handler(int sig) 37 { 38 } 39 40 static void *thr(void *v) 41 { 42 return 0; 43 } 44 45 #define FRAME 4096 46 47 static void grow(int depth) 48 { 49 volatile char frame[FRAME]; 50 51 memset((char *)frame, 0xff, sizeof(frame)); 52 53 if (depth > 1) 54 grow(depth-1); 55 } 56 57 static void *maker(void *v) 58 { 59 int i; 60 61 sleep(1); 62 63 /* Create lots of threads */ 64 printf("creating threads...\n"); 65 for(i = 0; i < 1300; i++) { 66 pthread_t t; 67 int ret; 68 69 if (i % 100 == 0) 70 printf("%d...\n", i); 71 72 ret = pthread_create(&t, NULL, thr, NULL); 73 if (ret) { 74 printf("pthread_create failed: %s\n", strerror(ret)); 75 exit(1); 76 } 77 78 ret = pthread_join(t, NULL); 79 if (ret) { 80 printf("pthread_join failed: %s\n", strerror(ret)); 81 exit(1); 82 } 83 } 84 85 kill(grower, SIGUSR1); 86 87 return NULL; 88 } 89 90 int main() 91 { 92 pthread_t pth; 93 sigset_t mask; 94 int status; 95 struct sigaction sa; 96 97 sigemptyset(&mask); 98 sigaddset(&mask, SIGCHLD); 99 sigprocmask(SIG_BLOCK, &mask, NULL); 100 101 sa.sa_handler = handler; 102 sa.sa_flags = 0; 103 sigfillset(&sa.sa_mask); 104 sigaction(SIGUSR1, &sa, NULL); 105 106 grower = fork(); 107 108 if (grower == -1) { 109 perror("fork"); 110 exit(1); 111 } 112 113 if (grower == 0) { 114 pause(); /* child - wait for SIGUSR1 */ 115 grow(10); 116 printf("stack grew OK\n"); 117 exit(0); 118 } 119 120 pthread_create(&pth, NULL, maker, NULL); 121 122 /* wait for child */ 123 if (waitpid(grower, &status, 0) != grower) 124 printf("FAILED\n"); 125 else if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 126 printf("PASS: child OK\n"); 127 else 128 printf("FAILED: exit status=%d\n", status); 129 130 pthread_join(pth, NULL); 131 132 return 0; 133 } 134