xref: /llvm-project/compiler-rt/test/rtsan/fork_exec.cpp (revision af4ae12780099d3df0b89bccc80fd69b240f345e)
1*af4ae127SChris Apple // RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=1 %s -o %t
2*af4ae127SChris Apple // RUN: %env_rtsan_opts="halt_on_error=true" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HALT
3*af4ae127SChris Apple // RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOHALT
4*af4ae127SChris Apple 
5*af4ae127SChris Apple // RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=0 %s -o %t
6*af4ae127SChris Apple // RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK
7*af4ae127SChris Apple // RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK
8*af4ae127SChris Apple 
9*af4ae127SChris Apple // UNSUPPORTED: ios
10*af4ae127SChris Apple 
11*af4ae127SChris Apple // Intent: Ensure fork/exec dies when realtime and survives otherwise
12*af4ae127SChris Apple //         This behavior is difficult to test in a gtest, because the process is
13*af4ae127SChris Apple //         wiped away with exec.
14*af4ae127SChris Apple 
15*af4ae127SChris Apple #include <stdio.h>
16*af4ae127SChris Apple #include <sys/types.h>
17*af4ae127SChris Apple #include <sys/wait.h>
18*af4ae127SChris Apple #include <unistd.h>
19*af4ae127SChris Apple 
20*af4ae127SChris Apple #if IS_NONBLOCKING
21*af4ae127SChris Apple #  define MAYBE_NONBLOCKING [[clang::nonblocking]]
22*af4ae127SChris Apple #else
23*af4ae127SChris Apple #  define MAYBE_NONBLOCKING
24*af4ae127SChris Apple #endif
25*af4ae127SChris Apple 
26*af4ae127SChris Apple int main() MAYBE_NONBLOCKING {
27*af4ae127SChris Apple   const pid_t pid = fork();
28*af4ae127SChris Apple 
29*af4ae127SChris Apple   if (pid == 0) {
30*af4ae127SChris Apple     char *args[] = {"/bin/ls", nullptr};
31*af4ae127SChris Apple     execve(args[0], args, nullptr);
32*af4ae127SChris Apple     perror("execve failed");
33*af4ae127SChris Apple     return 1;
34*af4ae127SChris Apple   } else if (pid > 0) {
35*af4ae127SChris Apple     int status;
36*af4ae127SChris Apple     waitpid(pid, &status, 0);
37*af4ae127SChris Apple     usleep(1);
38*af4ae127SChris Apple   } else {
39*af4ae127SChris Apple     perror("fork failed");
40*af4ae127SChris Apple     return 1;
41*af4ae127SChris Apple   }
42*af4ae127SChris Apple 
43*af4ae127SChris Apple   printf("fork/exec succeeded\n");
44*af4ae127SChris Apple   return 0;
45*af4ae127SChris Apple }
46*af4ae127SChris Apple 
47*af4ae127SChris Apple // CHECK-NOHALT: Intercepted call to {{.*}} `fork` {{.*}}
48*af4ae127SChris Apple // CHECK-NOHALT: Intercepted call to {{.*}} `execve` {{.*}}
49*af4ae127SChris Apple 
50*af4ae127SChris Apple // usleep checks that rtsan is still enabled in the parent process
51*af4ae127SChris Apple // See note in our interceptors file for why we don't look for `wait`
52*af4ae127SChris Apple // CHECK-NOHALT: Intercepted call to {{.*}} `usleep` {{.*}}
53*af4ae127SChris Apple 
54*af4ae127SChris Apple // CHECK-NOHALT: fork/exec succeeded
55*af4ae127SChris Apple 
56*af4ae127SChris Apple // CHECK-HALT: ==ERROR: RealtimeSanitizer: unsafe-library-call
57*af4ae127SChris Apple // CHECK-HALT-NEXT: Intercepted call to {{.*}} `fork` {{.*}}
58*af4ae127SChris Apple 
59*af4ae127SChris Apple // CHECK-OK: fork/exec succeeded
60