mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 18:18:06 +02:00
swr/rast: Better ExecCmd (i.e. system()) implmentation
Hides console window creation during JIT linker execution in apps that don't have a console. Remove hooking of CreateProcessInternalA - the MSFT implementation just turns around and calls CreateProcessInternalW which, we do hook. Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
This commit is contained in:
parent
2d16b61bff
commit
0b46c7b3b0
3 changed files with 169 additions and 34 deletions
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "common/os.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
|
@ -151,3 +152,160 @@ void SWR_API CreateDirectoryPath(const std::string& path)
|
|||
}
|
||||
#endif // Unix
|
||||
}
|
||||
|
||||
/// Execute Command (block until finished)
|
||||
/// @returns process exit value
|
||||
int SWR_API ExecCmd(
|
||||
const std::string& cmd, ///< (In) Command line string
|
||||
const char* pOptEnvStrings, ///< (Optional In) Environment block for new process
|
||||
std::string* pOptStdOut, ///< (Optional Out) Standard Output text
|
||||
std::string* pOptStdErr, ///< (Optional Out) Standard Error text
|
||||
const std::string* pOptStdIn) ///< (Optional In) Standard Input text
|
||||
{
|
||||
int rvalue = -1;
|
||||
|
||||
#if defined(_WIN32)
|
||||
struct WinPipe
|
||||
{
|
||||
HANDLE hRead;
|
||||
HANDLE hWrite;
|
||||
};
|
||||
std::array<WinPipe, 3> hPipes = {};
|
||||
|
||||
SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
|
||||
saAttr.bInheritHandle = TRUE; //Pipe handles are inherited by child process.
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
{
|
||||
bool bFail = false;
|
||||
for (WinPipe& p : hPipes)
|
||||
{
|
||||
if (!CreatePipe(&p.hRead, &p.hWrite, &saAttr, 0))
|
||||
{
|
||||
bFail = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFail)
|
||||
{
|
||||
for (WinPipe& p : hPipes)
|
||||
{
|
||||
CloseHandle(p.hRead);
|
||||
CloseHandle(p.hWrite);
|
||||
}
|
||||
return rvalue;
|
||||
}
|
||||
}
|
||||
|
||||
STARTUPINFOA StartupInfo{};
|
||||
StartupInfo.cb = sizeof(STARTUPINFOA);
|
||||
StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
StartupInfo.wShowWindow = SW_HIDE;
|
||||
if (pOptStdIn)
|
||||
{
|
||||
StartupInfo.hStdInput = hPipes[0].hRead;
|
||||
}
|
||||
StartupInfo.hStdOutput = hPipes[1].hWrite;
|
||||
StartupInfo.hStdError = hPipes[2].hWrite;
|
||||
PROCESS_INFORMATION procInfo{};
|
||||
|
||||
// CreateProcess can modify the string
|
||||
std::string local_cmd = cmd;
|
||||
|
||||
BOOL ProcessValue = CreateProcessA(
|
||||
NULL,
|
||||
(LPSTR)local_cmd.c_str(),
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
(LPVOID)pOptEnvStrings,
|
||||
NULL,
|
||||
&StartupInfo,
|
||||
&procInfo);
|
||||
|
||||
if (ProcessValue && procInfo.hProcess)
|
||||
{
|
||||
auto ReadFromPipe = [](HANDLE hPipe, std::string* pOutStr)
|
||||
{
|
||||
char buf[1024];
|
||||
DWORD dwRead = 0;
|
||||
DWORD dwAvail = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!::PeekNamedPipe(hPipe, NULL, 0, NULL, &dwAvail, NULL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dwAvail) // no data available, return
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!::ReadFile(hPipe, buf, std::min<size_t>(sizeof(buf) - 1, size_t(dwAvail)), &dwRead, NULL) || !dwRead)
|
||||
{
|
||||
// error, the child process might ended
|
||||
break;
|
||||
}
|
||||
|
||||
buf[dwRead] = 0;
|
||||
if (pOutStr)
|
||||
{
|
||||
(*pOutStr) += buf;
|
||||
}
|
||||
}
|
||||
};
|
||||
bool bProcessEnded = false;
|
||||
size_t bytesWritten = 0;
|
||||
do
|
||||
{
|
||||
if (pOptStdIn && (pOptStdIn->size() > bytesWritten))
|
||||
{
|
||||
DWORD bytesToWrite = static_cast<DWORD>(pOptStdIn->size()) - bytesWritten;
|
||||
if (!::WriteFile(
|
||||
hPipes[0].hWrite,
|
||||
pOptStdIn->data() + bytesWritten,
|
||||
bytesToWrite, &bytesToWrite, nullptr))
|
||||
{
|
||||
// Failed to write to pipe
|
||||
break;
|
||||
}
|
||||
bytesWritten += bytesToWrite;
|
||||
}
|
||||
|
||||
// Give some timeslice (50ms), so we won't waste 100% cpu.
|
||||
bProcessEnded = (WaitForSingleObject(procInfo.hProcess, 50) == WAIT_OBJECT_0);
|
||||
|
||||
ReadFromPipe(hPipes[1].hRead, pOptStdOut);
|
||||
ReadFromPipe(hPipes[2].hRead, pOptStdErr);
|
||||
}
|
||||
while (!bProcessEnded);
|
||||
|
||||
DWORD exitVal = 0;
|
||||
if (!GetExitCodeProcess(procInfo.hProcess, &exitVal))
|
||||
{
|
||||
exitVal = 1;
|
||||
}
|
||||
|
||||
CloseHandle(procInfo.hProcess);
|
||||
CloseHandle(procInfo.hThread);
|
||||
|
||||
rvalue = exitVal;
|
||||
}
|
||||
|
||||
for (WinPipe& p : hPipes)
|
||||
{
|
||||
CloseHandle(p.hRead);
|
||||
CloseHandle(p.hWrite);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Non-Windows implementation
|
||||
|
||||
#endif
|
||||
|
||||
return rvalue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,4 +280,13 @@ typedef MEGABYTE GIGABYTE[1024];
|
|||
void SWR_API SetCurrentThreadName(const char* pThreadName);
|
||||
void SWR_API CreateDirectoryPath(const std::string& path);
|
||||
|
||||
/// Execute Command (block until finished)
|
||||
/// @returns process exit value
|
||||
int SWR_API ExecCmd(
|
||||
const std::string& cmd, ///< (In) Command line string
|
||||
const char* pOptEnvStrings = nullptr, ///< (Optional In) Environment block for new process
|
||||
std::string* pOptStdOut = nullptr, ///< (Optional Out) Standard Output text
|
||||
std::string* pOptStdErr = nullptr, ///< (Optional Out) Standard Error text
|
||||
const std::string* pOptStdIn = nullptr); ///< (Optional In) Standard Input text
|
||||
|
||||
#endif//__SWR_OS_H__
|
||||
|
|
|
|||
|
|
@ -599,44 +599,12 @@ JitCache::JitCache()
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
int ExecUnhookedProcess(const char* pCmdLine)
|
||||
int ExecUnhookedProcess(const std::string& CmdLine, std::string* pStdOut, std::string* pStdErr)
|
||||
{
|
||||
static const char *g_pEnv = "RASTY_DISABLE_HOOK=1\0";
|
||||
|
||||
STARTUPINFOA StartupInfo{};
|
||||
StartupInfo.cb = sizeof(STARTUPINFOA);
|
||||
PROCESS_INFORMATION procInfo{};
|
||||
|
||||
BOOL ProcessValue = CreateProcessA(
|
||||
NULL,
|
||||
(LPSTR)pCmdLine,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
(LPVOID)g_pEnv,
|
||||
NULL,
|
||||
&StartupInfo,
|
||||
&procInfo);
|
||||
|
||||
if (ProcessValue && procInfo.hProcess)
|
||||
{
|
||||
WaitForSingleObject(procInfo.hProcess, INFINITE);
|
||||
DWORD exitVal = 0;
|
||||
if (!GetExitCodeProcess(procInfo.hProcess, &exitVal))
|
||||
{
|
||||
exitVal = 1;
|
||||
}
|
||||
|
||||
CloseHandle(procInfo.hProcess);
|
||||
|
||||
return exitVal;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return ExecCmd(CmdLine, g_pEnv, pStdOut, pStdErr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64) && defined(ENABLE_JIT_DEBUG) && defined(JIT_BASE_DIR)
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue