Teach ProcessWindows plugin to support stdio i/o redirection.

llvm-svn: 214816
This commit is contained in:
Zachary Turner 2014-08-04 23:31:21 +00:00
parent bc0b0378c5
commit f490bec4a1
1 changed files with 61 additions and 11 deletions

View File

@ -25,6 +25,42 @@
using namespace lldb;
using namespace lldb_private;
namespace
{
HANDLE
GetStdioHandle(ProcessLaunchInfo &launch_info, int fd)
{
const ProcessLaunchInfo::FileAction *action = launch_info.GetFileActionForFD(fd);
if (action == nullptr)
return NULL;
SECURITY_ATTRIBUTES secattr = {0};
secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
secattr.bInheritHandle = TRUE;
const char *path = action->GetPath();
DWORD access = 0;
DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD create = 0;
DWORD flags = 0;
if (fd == STDIN_FILENO)
{
access = GENERIC_READ;
create = OPEN_EXISTING;
flags = FILE_ATTRIBUTE_READONLY;
}
if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
{
access = GENERIC_WRITE;
create = CREATE_ALWAYS;
if (fd == STDERR_FILENO)
flags = FILE_FLAG_WRITE_THROUGH;
}
HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
return (result == INVALID_HANDLE_VALUE) ? NULL : result;
}
}
//------------------------------------------------------------------------------
// Static functions.
@ -91,20 +127,34 @@ ProcessWindows::DoLaunch(Module *exe_module,
std::vector<char> environment;
STARTUPINFO startupinfo = {0};
PROCESS_INFORMATION pi = {0};
HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags |= STARTF_USESTDHANDLES;
startupinfo.hStdError = stderr_handle;
startupinfo.hStdInput = stdin_handle;
startupinfo.hStdOutput = stdout_handle;
executable = launch_info.GetExecutableFile().GetPath();
launch_info.GetArguments().GetQuotedCommandString(commandLine);
BOOL result = ::CreateProcessA(executable.c_str(),
const_cast<char*>(commandLine.c_str()),
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
launch_info.GetWorkingDirectory(),
&startupinfo,
&pi);
BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE,
CREATE_NEW_CONSOLE, NULL, launch_info.GetWorkingDirectory(), &startupinfo, &pi);
if (result)
{
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
}
if (stdin_handle)
::CloseHandle(stdin_handle);
if (stdout_handle)
::CloseHandle(stdout_handle);
if (stderr_handle)
::CloseHandle(stderr_handle);
Error error;
if (!result)
error.SetErrorToErrno();