blob: 35d1d02ce94b5bbff4a111d6c9157ea8ac26076f [file] [log] [blame]
Reid Kleckner2a2bc722016-11-11 17:51:51 +00001// RUN: %clangxx_asan -g %stdcxx11 -Wno-deprecated-declarations %s -o %t
2// RUN: %env_asan_opts=exitcode=42 %t | FileCheck %s
3
4// CHECK: got expected 42 exit code
5
6#include <stdlib.h>
7#include <stdio.h>
8
9#ifdef _WIN32
10#include <windows.h>
11
12int spawn_child(char **argv) {
13 // Set an environment variable to tell the child process to interrupt
14 // itself.
15 if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) {
16 printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());
17 fflush(stdout);
18 exit(1);
19 }
20
21 STARTUPINFOW si;
22 memset(&si, 0, sizeof(si));
23 si.cb = sizeof(si);
24
25 PROCESS_INFORMATION pi;
26 memset(&pi, 0, sizeof(pi));
27
28 if (!CreateProcessW(nullptr, // No module name (use command line)
29 GetCommandLineW(), // Command line
30 nullptr, // Process handle not inheritable
31 nullptr, // Thread handle not inheritable
32 TRUE, // Set handle inheritance to TRUE
33 0, // No flags
34 nullptr, // Use parent's environment block
35 nullptr, // Use parent's starting directory
36 &si, &pi)) {
37 printf("CreateProcess failed (0x%08lx).\n", GetLastError());
38 fflush(stdout);
39 exit(1);
40 }
41
42 WaitForSingleObject(pi.hProcess, INFINITE);
43
44 DWORD exit_code;
45 if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {
46 printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());
47 fflush(stdout);
48 exit(1);
49 }
50
51 CloseHandle(pi.hProcess);
52 CloseHandle(pi.hThread);
53
54 return exit_code;
55}
56#else
57#include <spawn.h>
58#include <errno.h>
59#include <sys/wait.h>
60
61#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
62#define USE_NSGETENVIRON 1
63#else
64#define USE_NSGETENVIRON 0
65#endif
66
67#if !USE_NSGETENVIRON
68extern char **environ;
69#else
70#include <crt_externs.h> // _NSGetEnviron
71#endif
72
73int spawn_child(char **argv) {
74 setenv("CRASH_FOR_TEST", "1", 1);
75
76#if !USE_NSGETENVIRON
77 char **envp = environ;
78#else
79 char **envp = *_NSGetEnviron();
80#endif
81
82 pid_t pid;
83 int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp);
84 if (err) {
85 printf("posix_spawn failed: %d\n", err);
86 fflush(stdout);
87 exit(1);
88 }
89
90 // Wait until the child exits.
91 int status;
92 pid_t wait_result_pid;
93 do {
94 wait_result_pid = waitpid(pid, &status, 0);
95 } while (wait_result_pid == -1 && errno == EINTR);
96
97 if (wait_result_pid != pid || !WIFEXITED(status)) {
98 printf("error in waitpid\n");
99 fflush(stdout);
100 exit(1);
101 }
102
103 // Return the exit status.
104 return WEXITSTATUS(status);
105}
106#endif
107
108int main(int argc, char **argv) {
109 int r = 0;
110 if (getenv("CRASH_FOR_TEST")) {
111 // Generate an asan report to test ASAN_OPTIONS=exitcode=42
112 int *p = new int;
113 delete p;
114 r = *p;
115 } else {
116 int exit_code = spawn_child(argv);
117 if (exit_code == 42) {
118 printf("got expected 42 exit code\n");
119 fflush(stdout);
120 }
121 }
122 return r;
123}