diff options
Diffstat (limited to 'test/asan/TestCases/exitcode.cpp')
-rw-r--r-- | test/asan/TestCases/exitcode.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/test/asan/TestCases/exitcode.cpp b/test/asan/TestCases/exitcode.cpp new file mode 100644 index 000000000..cb1054099 --- /dev/null +++ b/test/asan/TestCases/exitcode.cpp @@ -0,0 +1,130 @@ +// RUN: %clangxx_asan -g %stdcxx11 -Wno-deprecated-declarations %s -o %t +// RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s + +// Android doesn't have spawn.h or posix_spawn. +// UNSUPPORTED: android + +// CHECK: got expected 42 exit code + +#include <stdlib.h> +#include <stdio.h> + +#ifdef _WIN32 +#include <windows.h> + +int spawn_child(char **argv) { + // Set an environment variable to tell the child process to interrupt + // itself. + if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) { + printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + STARTUPINFOW si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + if (!CreateProcessW(nullptr, // No module name (use command line) + GetCommandLineW(), // Command line + nullptr, // Process handle not inheritable + nullptr, // Thread handle not inheritable + TRUE, // Set handle inheritance to TRUE + 0, // No flags + nullptr, // Use parent's environment block + nullptr, // Use parent's starting directory + &si, &pi)) { + printf("CreateProcess failed (0x%08lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code; + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { + printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return exit_code; +} +#else +#include <spawn.h> +#include <errno.h> +#include <sys/wait.h> + +#if defined(__APPLE__) +#include <TargetConditionals.h> +#endif + +#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define USE_NSGETENVIRON 1 +#else +#define USE_NSGETENVIRON 0 +#endif + +#if !USE_NSGETENVIRON +extern char **environ; +#else +#include <crt_externs.h> // _NSGetEnviron +#endif + +int spawn_child(char **argv) { + setenv("CRASH_FOR_TEST", "1", 1); + +#if !USE_NSGETENVIRON + char **envp = environ; +#else + char **envp = *_NSGetEnviron(); +#endif + + pid_t pid; + int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp); + if (err) { + printf("posix_spawn failed: %d\n", err); + fflush(stdout); + exit(1); + } + + // Wait until the child exits. + int status; + pid_t wait_result_pid; + do { + wait_result_pid = waitpid(pid, &status, 0); + } while (wait_result_pid == -1 && errno == EINTR); + + if (wait_result_pid != pid || !WIFEXITED(status)) { + printf("error in waitpid\n"); + fflush(stdout); + exit(1); + } + + // Return the exit status. + return WEXITSTATUS(status); +} +#endif + +int main(int argc, char **argv) { + int r = 0; + if (getenv("CRASH_FOR_TEST")) { + // Generate an asan report to test ASAN_OPTIONS=exitcode=42 + int *p = new int; + delete p; + r = *p; + } else { + int exit_code = spawn_child(argv); + if (exit_code == 42) { + printf("got expected 42 exit code\n"); + fflush(stdout); + } + } + return r; +} |