xref: /llvm-project/compiler-rt/test/asan/TestCases/exitcode.cpp (revision 882ce178b317c565f14b0de05a2c9ee39fe78a83)
1*882ce178SVitaly Buka // RUN: %clangxx_asan -g -Wno-deprecated-declarations %s -o %t
2673dc3d4SNico Weber // RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s
3673dc3d4SNico Weber 
4673dc3d4SNico Weber // Android doesn't have spawn.h or posix_spawn.
5673dc3d4SNico Weber // UNSUPPORTED: android
6673dc3d4SNico Weber 
7673dc3d4SNico Weber // CHECK: got expected 42 exit code
8673dc3d4SNico Weber 
9673dc3d4SNico Weber #include <stdlib.h>
10673dc3d4SNico Weber #include <stdio.h>
11673dc3d4SNico Weber 
12673dc3d4SNico Weber #ifdef _WIN32
13673dc3d4SNico Weber #include <windows.h>
14673dc3d4SNico Weber 
spawn_child(char ** argv)15673dc3d4SNico Weber int spawn_child(char **argv) {
16673dc3d4SNico Weber   // Set an environment variable to tell the child process to interrupt
17673dc3d4SNico Weber   // itself.
18673dc3d4SNico Weber   if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) {
19673dc3d4SNico Weber     printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());
20673dc3d4SNico Weber     fflush(stdout);
21673dc3d4SNico Weber     exit(1);
22673dc3d4SNico Weber   }
23673dc3d4SNico Weber 
24673dc3d4SNico Weber   STARTUPINFOW si;
25673dc3d4SNico Weber   memset(&si, 0, sizeof(si));
26673dc3d4SNico Weber   si.cb = sizeof(si);
27673dc3d4SNico Weber 
28673dc3d4SNico Weber   PROCESS_INFORMATION pi;
29673dc3d4SNico Weber   memset(&pi, 0, sizeof(pi));
30673dc3d4SNico Weber 
31673dc3d4SNico Weber   if (!CreateProcessW(nullptr,           // No module name (use command line)
32673dc3d4SNico Weber                       GetCommandLineW(), // Command line
33673dc3d4SNico Weber                       nullptr,           // Process handle not inheritable
34673dc3d4SNico Weber                       nullptr,           // Thread handle not inheritable
35673dc3d4SNico Weber                       TRUE,              // Set handle inheritance to TRUE
36673dc3d4SNico Weber                       0,                 // No flags
37673dc3d4SNico Weber                       nullptr,           // Use parent's environment block
38673dc3d4SNico Weber                       nullptr,           // Use parent's starting directory
39673dc3d4SNico Weber                       &si, &pi)) {
40673dc3d4SNico Weber     printf("CreateProcess failed (0x%08lx).\n", GetLastError());
41673dc3d4SNico Weber     fflush(stdout);
42673dc3d4SNico Weber     exit(1);
43673dc3d4SNico Weber   }
44673dc3d4SNico Weber 
45673dc3d4SNico Weber   WaitForSingleObject(pi.hProcess, INFINITE);
46673dc3d4SNico Weber 
47673dc3d4SNico Weber   DWORD exit_code;
48673dc3d4SNico Weber   if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {
49673dc3d4SNico Weber     printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());
50673dc3d4SNico Weber     fflush(stdout);
51673dc3d4SNico Weber     exit(1);
52673dc3d4SNico Weber   }
53673dc3d4SNico Weber 
54673dc3d4SNico Weber   CloseHandle(pi.hProcess);
55673dc3d4SNico Weber   CloseHandle(pi.hThread);
56673dc3d4SNico Weber 
57673dc3d4SNico Weber   return exit_code;
58673dc3d4SNico Weber }
59673dc3d4SNico Weber #else
60673dc3d4SNico Weber #include <spawn.h>
61673dc3d4SNico Weber #include <errno.h>
62673dc3d4SNico Weber #include <sys/wait.h>
63673dc3d4SNico Weber 
64673dc3d4SNico Weber #if defined(__APPLE__)
65673dc3d4SNico Weber #include <TargetConditionals.h>
66673dc3d4SNico Weber #endif
67673dc3d4SNico Weber 
68673dc3d4SNico Weber #if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
69673dc3d4SNico Weber #define USE_NSGETENVIRON 1
70673dc3d4SNico Weber #else
71673dc3d4SNico Weber #define USE_NSGETENVIRON 0
72673dc3d4SNico Weber #endif
73673dc3d4SNico Weber 
74673dc3d4SNico Weber #if !USE_NSGETENVIRON
75673dc3d4SNico Weber extern char **environ;
76673dc3d4SNico Weber #else
77673dc3d4SNico Weber #include <crt_externs.h> // _NSGetEnviron
78673dc3d4SNico Weber #endif
79673dc3d4SNico Weber 
spawn_child(char ** argv)80673dc3d4SNico Weber int spawn_child(char **argv) {
81673dc3d4SNico Weber   setenv("CRASH_FOR_TEST", "1", 1);
82673dc3d4SNico Weber 
83673dc3d4SNico Weber #if !USE_NSGETENVIRON
84673dc3d4SNico Weber   char **envp = environ;
85673dc3d4SNico Weber #else
86673dc3d4SNico Weber   char **envp = *_NSGetEnviron();
87673dc3d4SNico Weber #endif
88673dc3d4SNico Weber 
89673dc3d4SNico Weber   pid_t pid;
90673dc3d4SNico Weber   int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp);
91673dc3d4SNico Weber   if (err) {
92673dc3d4SNico Weber     printf("posix_spawn failed: %d\n", err);
93673dc3d4SNico Weber     fflush(stdout);
94673dc3d4SNico Weber     exit(1);
95673dc3d4SNico Weber   }
96673dc3d4SNico Weber 
97673dc3d4SNico Weber   // Wait until the child exits.
98673dc3d4SNico Weber   int status;
99673dc3d4SNico Weber   pid_t wait_result_pid;
100673dc3d4SNico Weber   do {
101673dc3d4SNico Weber     wait_result_pid = waitpid(pid, &status, 0);
102673dc3d4SNico Weber   } while (wait_result_pid == -1 && errno == EINTR);
103673dc3d4SNico Weber 
104673dc3d4SNico Weber   if (wait_result_pid != pid || !WIFEXITED(status)) {
105673dc3d4SNico Weber     printf("error in waitpid\n");
106673dc3d4SNico Weber     fflush(stdout);
107673dc3d4SNico Weber     exit(1);
108673dc3d4SNico Weber   }
109673dc3d4SNico Weber 
110673dc3d4SNico Weber   // Return the exit status.
111673dc3d4SNico Weber   return WEXITSTATUS(status);
112673dc3d4SNico Weber }
113673dc3d4SNico Weber #endif
114673dc3d4SNico Weber 
main(int argc,char ** argv)115673dc3d4SNico Weber int main(int argc, char **argv) {
116673dc3d4SNico Weber   int r = 0;
117673dc3d4SNico Weber   if (getenv("CRASH_FOR_TEST")) {
118673dc3d4SNico Weber     // Generate an asan report to test ASAN_OPTIONS=exitcode=42
119673dc3d4SNico Weber     int *p = new int;
120673dc3d4SNico Weber     delete p;
121673dc3d4SNico Weber     r = *p;
122673dc3d4SNico Weber   } else {
123673dc3d4SNico Weber     int exit_code = spawn_child(argv);
124673dc3d4SNico Weber     if (exit_code == 42) {
125673dc3d4SNico Weber       printf("got expected 42 exit code\n");
126673dc3d4SNico Weber       fflush(stdout);
127673dc3d4SNico Weber     }
128673dc3d4SNico Weber   }
129673dc3d4SNico Weber   return r;
130673dc3d4SNico Weber }
131