Home | History | Annotate | Download | only in Linux
      1 // Test StopTheWorld behavior during signal storm.
      2 // Historically StopTheWorld crashed because did not handle EINTR properly.
      3 // The test is somewhat convoluted, but that's what caused crashes previously.
      4 
      5 // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <signal.h>
     10 #include <unistd.h>
     11 #include <sys/types.h>
     12 #include <sys/prctl.h>
     13 #include <sys/wait.h>
     14 #include <time.h>
     15 #include <pthread.h>
     16 #include <sanitizer/lsan_interface.h>
     17 
     18 static void handler(int signo);
     19 static void *thr(void *arg);
     20 
     21 int main() {
     22   struct sigaction act = {};
     23   act.sa_handler = handler;
     24   sigaction(SIGPROF, &act, 0);
     25 
     26   pid_t pid = fork();
     27   if (pid < 0) {
     28     fprintf(stderr, "failed to fork\n");
     29     exit(1);
     30   }
     31   if (pid == 0) {
     32     // Child constantly sends signals to parent to cause spurious return from
     33     // waitpid in StopTheWorld.
     34     prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
     35     pid_t parent = getppid();
     36     for (;;) {
     37       // There is no strong reason for these two particular signals,
     38       // but at least one of them ought to unblock waitpid.
     39       kill(parent, SIGCHLD);
     40       kill(parent, SIGPROF);
     41     }
     42   }
     43   usleep(10000);  // Let the child start.
     44   __lsan_do_leak_check();
     45   // Kill and join the child.
     46   kill(pid, SIGTERM);
     47   waitpid(pid, 0, 0);
     48   sleep(1);  // If the tracer thread still runs, give it time to crash.
     49   fprintf(stderr, "DONE\n");
     50 // CHECK: DONE
     51 }
     52 
     53 static void handler(int signo) {
     54 }
     55 
     56 static void *thr(void *arg) {
     57   for (;;)
     58     sleep(1);
     59   return 0;
     60 }
     61