--- parser3/src/main/pa_exec.C 2013/07/22 15:17:06 1.83 +++ parser3/src/main/pa_exec.C 2015/10/28 22:50:00 1.87 @@ -1,7 +1,7 @@ /** @file Parser: program executing for different OS-es. - Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) @todo setrlimit @@ -13,9 +13,9 @@ #include "pa_exception.h" #include "pa_common.h" -volatile const char * IDENT_PA_EXEC_C="$Id: pa_exec.C,v 1.83 2013/07/22 15:17:06 moko Exp $" IDENT_PA_EXEC_H; +volatile const char * IDENT_PA_EXEC_C="$Id: pa_exec.C,v 1.87 2015/10/28 22:50:00 moko Exp $" IDENT_PA_EXEC_H; -#ifdef WIN32 +#ifdef _MSC_VER #include @@ -45,15 +45,27 @@ static DWORD CreateHiddenConsoleProcess( // create STDIN pipe if(!CreatePipe(&hInRead, phInWrite, &sa, 0)) goto error; - + + // Ensure the write handle to the pipe for STDIN is not inherited. + if (!SetHandleInformation(*phInWrite, HANDLE_FLAG_INHERIT, 0)) + goto error; + // create STDOUT pipe if(!CreatePipe(phOutRead, &hOutWrite, &sa, 0)) goto error; + // Ensure the read handle to the pipe for STDOUT is not inherited. + if (!SetHandleInformation(*phOutRead, HANDLE_FLAG_INHERIT, 0)) + goto error; + // create STDERR pipe if(!CreatePipe(phErrRead, &hErrWrite, &sa, 0)) goto error; + // Ensure the read handle to the pipe for STDERR is not inherited. + if (!SetHandleInformation(*phErrRead, HANDLE_FLAG_INHERIT, 0)) + goto error; + // process startup information memset(&si, 0, sizeof(si)); si.cb=sizeof(si); @@ -105,6 +117,20 @@ error: return result; } +static int get_exit_status(HANDLE hProcess) { + DWORD dwExitCode = 0; + if(!GetExitCodeProcess(hProcess, &dwExitCode)) + return -1; + if(dwExitCode != STILL_ACTIVE) + return dwExitCode; + // wait for 1 second for process to exit + if(WaitForSingleObject(hProcess, 1000) != WAIT_OBJECT_0) + return -2; + if(!GetExitCodeProcess(hProcess, &dwExitCode)) + return -1; + return dwExitCode; +} + static void read_pipe(String& result, HANDLE hOutRead, String::Language lang){ while(true) { char *buf=new(PointerFreeGC) char[MAX_STRING+1]; @@ -333,7 +359,7 @@ static void read_pipe(File_read_result& #ifndef DOXYGEN struct Append_env_pair_info { -#ifdef WIN32 +#ifdef _MSC_VER String::Body& body; Append_env_pair_info(String::Body& abody): body(abody) {} #else @@ -345,7 +371,7 @@ struct Append_env_pair_info { ///@test maybe here and at argv construction --- untaint_cstr(String::L_AS_IS static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value, Append_env_pair_info *info) { -#ifdef WIN32 +#ifdef _MSC_VER info->body << key << "=" << value; info->body.append_know_length("\1", 1); // placeholder for of zero byte #else @@ -371,7 +397,7 @@ PA_exec_result pa_exec( "parser execs are disabled [recompile parser without --disable-execs configure option]"); #endif -#ifdef WIN32 +#ifdef _MSC_VER PROCESS_INFORMATION pi; HANDLE hInWrite, hOutRead, hErrRead; @@ -405,15 +431,12 @@ PA_exec_result pa_exec( const char* in_cstr=in.cstr(); DWORD written_size; WriteFile(hInWrite, in_cstr, in.length(), &written_size, NULL); - // EOF for stupid text reads - // normally they should read CONTENT_LENGTH bytes, - // without this char - WriteFile(hInWrite, "\x1A", 1, &written_size, NULL); CloseHandle(hInWrite); read_pipe(result.out, hOutRead); CloseHandle(hOutRead); read_pipe(result.err, hErrRead, String::L_TAINTED); CloseHandle(hErrRead); + result.status=get_exit_status(pi.hProcess); // We must close the handles to the new process and its main thread // to prevent handle and memory leaks. CloseHandle(pi.hProcess);