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