#include <unistd.h> #include <sys/types.h> #include <signal.h> #include <sys/wait.h> #include <stdio.h> #include <string.h> /* Expected order is: * Child signals parent * Parent got signal * Child will exit now * * The bug we test for: under strace -f, last two lines are swapped * because wait syscall is suspended by strace and thus can't be interrupted. */ static const char msg1[] = "Child signals parent\n"; static const char msg2[] = "Parent got signal\n"; static const char msg3[] = "Child will exit now\n"; static void handler(int s) { write(1, msg2, sizeof(msg2)-1); } static void test() { /* Note: in Linux, signal() installs handler with SA_RESTART flag, * therefore wait will be restarted. */ signal(SIGALRM, handler); if (fork() == 0) { /* child */ sleep(1); write(1, msg1, sizeof(msg1)-1); kill(getppid(), SIGALRM); sleep(1); write(1, msg3, sizeof(msg3)-1); _exit(0); } /* parent */ wait(NULL); _exit(0); } int main() { char buf1[80]; char buf2[80]; char buf3[80]; int pipefd[2]; printf("Please run me under 'strace -f'\n"); pipe(pipefd); if (fork() == 0) { if (pipefd[1] != 1) { dup2(pipefd[1], 1); close(pipefd[1]); } test(); } if (pipefd[0] != 0) { dup2(pipefd[0], 0); close(pipefd[0]); } fgets(buf1, 80, stdin); printf("%s", buf1); fgets(buf2, 80, stdin); printf("%s", buf2); fgets(buf3, 80, stdin); printf("%s", buf3); if (strcmp(buf1, msg1) != 0 || strcmp(buf2, msg2) != 0 || strcmp(buf3, msg3) != 0 ) { printf("ERROR! Expected order:\n%s%s%s", msg1, msg2, msg3); return 1; } printf("Good: wait seems to be correctly interrupted by signals\n"); return 0; }