131 lines · cpp
1// RUN: %clangxx_asan -g %if !MSVC %{ -Wno-deprecated-declarations %} %s -o %t2// RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s3 4// Android doesn't have spawn.h or posix_spawn.5// UNSUPPORTED: android6 7// CHECK: got expected 42 exit code8 9#include <stdlib.h>10#include <stdio.h>11 12#ifdef _WIN3213#include <windows.h>14 15int spawn_child(char **argv) {16 // Set an environment variable to tell the child process to interrupt17 // itself.18 if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) {19 printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());20 fflush(stdout);21 exit(1);22 }23 24 STARTUPINFOW si;25 memset(&si, 0, sizeof(si));26 si.cb = sizeof(si);27 28 PROCESS_INFORMATION pi;29 memset(&pi, 0, sizeof(pi));30 31 if (!CreateProcessW(nullptr, // No module name (use command line)32 GetCommandLineW(), // Command line33 nullptr, // Process handle not inheritable34 nullptr, // Thread handle not inheritable35 TRUE, // Set handle inheritance to TRUE36 0, // No flags37 nullptr, // Use parent's environment block38 nullptr, // Use parent's starting directory39 &si, &pi)) {40 printf("CreateProcess failed (0x%08lx).\n", GetLastError());41 fflush(stdout);42 exit(1);43 }44 45 WaitForSingleObject(pi.hProcess, INFINITE);46 47 DWORD exit_code;48 if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {49 printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());50 fflush(stdout);51 exit(1);52 }53 54 CloseHandle(pi.hProcess);55 CloseHandle(pi.hThread);56 57 return exit_code;58}59#else60#include <spawn.h>61#include <errno.h>62#include <sys/wait.h>63 64#if defined(__APPLE__)65#include <TargetConditionals.h>66#endif67 68#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)69#define USE_NSGETENVIRON 170#else71#define USE_NSGETENVIRON 072#endif73 74#if !USE_NSGETENVIRON75extern char **environ;76#else77#include <crt_externs.h> // _NSGetEnviron78#endif79 80int spawn_child(char **argv) {81 setenv("CRASH_FOR_TEST", "1", 1);82 83#if !USE_NSGETENVIRON84 char **envp = environ;85#else86 char **envp = *_NSGetEnviron();87#endif88 89 pid_t pid;90 int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp);91 if (err) {92 printf("posix_spawn failed: %d\n", err);93 fflush(stdout);94 exit(1);95 }96 97 // Wait until the child exits.98 int status;99 pid_t wait_result_pid;100 do {101 wait_result_pid = waitpid(pid, &status, 0);102 } while (wait_result_pid == -1 && errno == EINTR);103 104 if (wait_result_pid != pid || !WIFEXITED(status)) {105 printf("error in waitpid\n");106 fflush(stdout);107 exit(1);108 }109 110 // Return the exit status.111 return WEXITSTATUS(status);112}113#endif114 115int main(int argc, char **argv) {116 int r = 0;117 if (getenv("CRASH_FOR_TEST")) {118 // Generate an asan report to test ASAN_OPTIONS=exitcode=42119 int *p = new int;120 delete p;121 r = *p;122 } else {123 int exit_code = spawn_child(argv);124 if (exit_code == 42) {125 printf("got expected 42 exit code\n");126 fflush(stdout);127 }128 }129 return r;130}131