/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ int execute(char **argv, const char *path_stdout, const char *path_stderr) { #ifdef _WIN32 PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; BOOL ret; DWORD exitcode; char *args; HANDLE fd_out, fd_err; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; fd_out = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fd_out == INVALID_HANDLE_VALUE) { return STATUS_NOCACHE; } fd_err = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fd_err == INVALID_HANDLE_VALUE) { return STATUS_NOCACHE; } ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&sinfo, sizeof(STARTUPINFO)); sinfo.cb = sizeof(STARTUPINFO); sinfo.hStdError = fd_err; sinfo.hStdOutput = fd_out; sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); sinfo.dwFlags |= STARTF_USESTDHANDLES; args = argvtos(argv); ret = CreateProcessA(argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo); free(args); CloseHandle(fd_out); CloseHandle(fd_err); if (ret == 0) return -1; WaitForSingleObject(pinfo.hProcess, INFINITE); GetExitCodeProcess(pinfo.hProcess, &exitcode); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); return exitcode; #else pid_t pid; int status; pid = fork(); if (pid == -1) fatal("Failed to fork"); if (pid == 0) { int fd; unlink(path_stdout); fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(STATUS_NOCACHE); } dup2(fd, 1); close(fd); unlink(path_stderr); fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(STATUS_NOCACHE); } dup2(fd, 2); close(fd); exit(execv(argv[0], argv)); } if (waitpid(pid, &status, 0) != pid) { fatal("waitpid failed"); } if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } return WEXITSTATUS(status); #endif }
/* something went badly wrong - just execute the real compiler */ static void failed(void) { char *e; /* delete intermediate pre-processor file if needed */ if (i_tmpfile) { if (!direct_i_file) { unlink(i_tmpfile); } free(i_tmpfile); i_tmpfile = NULL; } /* delete the cpp stderr file if necessary */ if (cpp_stderr) { unlink(cpp_stderr); free(cpp_stderr); cpp_stderr = NULL; } /* strip any local args */ args_strip(orig_args, "--ccache-"); if ((e=getenv("CCACHE_PREFIX"))) { char *p = find_executable(e, MYNAME); if (!p) { cc_log("could not find executable (%s)\n", e); perror(e); exit(1); } args_add_prefix(orig_args, p); } if (ccache_verbose) { display_execute_args(orig_args->argv); } if (swig) { putenv("CCACHE_OUTFILES"); } #ifndef _WIN32 execv(orig_args->argv[0], orig_args->argv); cc_log("execv returned (%s)!\n", strerror(errno)); perror(orig_args->argv[0]); exit(1); #else /* execv on Windows causes the 'non-regular' testcase to fail, so use Win32 API instead */ { PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; BOOL ret; DWORD exitcode; char *args; ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&sinfo, sizeof(STARTUPINFO)); sinfo.cb = sizeof(STARTUPINFO); args = argvtos(orig_args->argv); ret = CreateProcessA(orig_args->argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo); if (!ret) { exitcode = 1; cc_log("CreateProcessA failed starting %s\n", orig_args->argv[0]); perror_win32(orig_args->argv[0]); } else { WaitForSingleObject(pinfo.hProcess, INFINITE); GetExitCodeProcess(pinfo.hProcess, &exitcode); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); } free(args); exit(exitcode); } #endif }