1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <signal.h> 4 #include <sys/wait.h> 5 #include <stdio.h> 6 #include <string.h> 7 8 /* Expected order is: 9 * Child signals parent 10 * Parent got signal 11 * Child will exit now 12 * 13 * The bug we test for: under strace -f, last two lines are swapped 14 * because wait syscall is suspended by strace and thus can't be interrupted. 15 */ 16 17 static const char msg1[] = "Child signals parent\n"; 18 static const char msg2[] = "Parent got signal\n"; 19 static const char msg3[] = "Child will exit now\n"; 20 21 static void handler(int s) 22 { 23 write(1, msg2, sizeof(msg2)-1); 24 } 25 26 static void test() 27 { 28 /* Note: in Linux, signal() installs handler with SA_RESTART flag, 29 * therefore wait will be restarted. 30 */ 31 signal(SIGALRM, handler); 32 33 if (fork() == 0) { 34 /* child */ 35 sleep(1); 36 write(1, msg1, sizeof(msg1)-1); 37 kill(getppid(), SIGALRM); 38 sleep(1); 39 write(1, msg3, sizeof(msg3)-1); 40 _exit(0); 41 } 42 43 /* parent */ 44 wait(NULL); 45 _exit(0); 46 } 47 48 int main() 49 { 50 char buf1[80]; 51 char buf2[80]; 52 char buf3[80]; 53 int pipefd[2]; 54 55 printf("Please run me under 'strace -f'\n"); 56 57 pipe(pipefd); 58 59 if (fork() == 0) { 60 if (pipefd[1] != 1) { 61 dup2(pipefd[1], 1); 62 close(pipefd[1]); 63 } 64 test(); 65 } 66 67 if (pipefd[0] != 0) { 68 dup2(pipefd[0], 0); 69 close(pipefd[0]); 70 } 71 fgets(buf1, 80, stdin); printf("%s", buf1); 72 fgets(buf2, 80, stdin); printf("%s", buf2); 73 fgets(buf3, 80, stdin); printf("%s", buf3); 74 75 if (strcmp(buf1, msg1) != 0 76 || strcmp(buf2, msg2) != 0 77 || strcmp(buf3, msg3) != 0 78 ) { 79 printf("ERROR! Expected order:\n%s%s%s", msg1, msg2, msg3); 80 return 1; 81 } 82 printf("Good: wait seems to be correctly interrupted by signals\n"); 83 return 0; 84 } 85