65 lines · cpp
1// RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=1 %s -o %t2// RUN: %env_rtsan_opts="halt_on_error=true" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HALT3// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOHALT4 5// RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=0 %s -o %t6// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK7// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK8 9// UNSUPPORTED: ios10 11// Intent: Ensure fork/exec dies when realtime and survives otherwise12// This behavior is difficult to test in a gtest, because the process is13// wiped away with exec.14 15#include <stdio.h>16#include <sys/types.h>17#include <sys/wait.h>18#include <unistd.h>19 20#if IS_NONBLOCKING21# define MAYBE_NONBLOCKING [[clang::nonblocking]]22#else23# define MAYBE_NONBLOCKING24#endif25 26int main() MAYBE_NONBLOCKING {27 const pid_t pid = fork();28 29 if (pid == 0) {30 char *args[] = {"/bin/ls", nullptr};31 execve(args[0], args, nullptr);32 perror("execve failed");33 return 1;34 } else if (pid > 0) {35 int status;36 waitpid(pid, &status, 0);37 usleep(1);38 } else {39 perror("fork failed");40 return 1;41 }42 43 printf("fork/exec succeeded\n");44 return 0;45}46 47// CHECK-NOHALT: Intercepted call to {{.*}} `fork` {{.*}}48 49// We should also get some other intercepted call. On some systems this50// is `execve`, on others, it's a lock to set up `execve`. In either51// case, just check that we get a second intercepted call, don't sweat52// the name.53// CHECK-NOHALT: Intercepted call to {{.*}}54 55// usleep checks that rtsan is still enabled in the parent process56// See note in our interceptors file for why we don't look for `wait`57// CHECK-NOHALT: Intercepted call to {{.*}} `usleep` {{.*}}58 59// CHECK-NOHALT: fork/exec succeeded60 61// CHECK-HALT: ==ERROR: RealtimeSanitizer: unsafe-library-call62// CHECK-HALT-NEXT: Intercepted call to {{.*}} `fork` {{.*}}63 64// CHECK-OK: fork/exec succeeded65