diff options
Diffstat (limited to 'lldb/source/Host')
-rw-r--r-- | lldb/source/Host/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lldb/source/Host/common/Host.cpp | 128 | ||||
-rw-r--r-- | lldb/source/Host/common/HostProcess.cpp | 7 | ||||
-rw-r--r-- | lldb/source/Host/common/MonitoringProcessLauncher.cpp | 102 | ||||
-rw-r--r-- | lldb/source/Host/macosx/Host.mm | 8 | ||||
-rw-r--r-- | lldb/source/Host/posix/HostProcessPosix.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Host/posix/ProcessLauncherPosix.cpp | 33 | ||||
-rw-r--r-- | lldb/source/Host/windows/Host.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Host/windows/HostProcessWindows.cpp | 49 | ||||
-rw-r--r-- | lldb/source/Host/windows/ProcessLauncherWindows.cpp | 94 |
10 files changed, 331 insertions, 110 deletions
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 73da2a890af..85211f9f017 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -16,6 +16,7 @@ add_host_subdirectory(common common/HostThread.cpp common/IOObject.cpp common/Mutex.cpp + common/MonitoringProcessLauncher.cpp common/NativeBreakpoint.cpp common/NativeBreakpointList.cpp common/NativeProcessProtocol.cpp @@ -48,6 +49,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") windows/HostThreadWindows.cpp windows/Mutex.cpp windows/PipeWindows.cpp + windows/ProcessLauncherWindows.cpp windows/ProcessRunLock.cpp windows/ThisThread.cpp windows/Windows.cpp @@ -59,6 +61,7 @@ else() posix/HostProcessPosix.cpp posix/HostThreadPosix.cpp posix/PipePosix.cpp + posix/ProcessLauncherPosix.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Darwin") diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 09376d2d443..ee0cb197105 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -71,7 +71,10 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/lldb-private-forward.h" #include "lldb/Target/FileAction.h" @@ -86,6 +89,12 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#if defined(_WIN32) +#include "lldb/Host/windows/ProcessLauncherWindows.h" +#else +#include "lldb/Host/posix/ProcessLauncherPosix.h" +#endif + #if defined (__APPLE__) #ifndef _POSIX_SPAWN_DISABLE_ASLR #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 @@ -717,7 +726,7 @@ Host::RunShellCommand (const char *command, // common/Host.cpp. short -Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) +Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { #ifndef __ANDROID__ short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; @@ -769,7 +778,7 @@ Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) } Error -Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) +Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { Error error; #ifndef __ANDROID__ @@ -890,6 +899,7 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i #endif } + ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; const size_t num_file_actions = launch_info.GetNumFileActions (); if (num_file_actions > 0) { @@ -914,21 +924,13 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } } - error.SetError (::posix_spawnp (&pid, - exe_path, - &file_actions, - &attr, - argv, - envp), - eErrorTypePOSIX); + error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail() || log) { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", - pid, exe_path, static_cast<void*>(&file_actions), - static_cast<void*>(&attr), - reinterpret_cast<const void*>(argv), - reinterpret_cast<const void*>(envp)); + error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid, + exe_path, static_cast<void *>(&file_actions), static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), + reinterpret_cast<const void *>(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -939,20 +941,13 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } else { - error.SetError (::posix_spawnp (&pid, - exe_path, - NULL, - &attr, - argv, - envp), - eErrorTypePOSIX); + error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail() || log) { error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", - pid, exe_path, static_cast<void*>(&attr), - reinterpret_cast<const void*>(argv), - reinterpret_cast<const void*>(envp)); + result_pid, exe_path, static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), + reinterpret_cast<const void *>(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -960,6 +955,7 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } } } + pid = result_pid; if (working_dir) { @@ -1056,86 +1052,28 @@ Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log * #endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32) // The functions below implement process launching via posix_spawn() for Linux, // FreeBSD and NetBSD. Error Host::LaunchProcess (ProcessLaunchInfo &launch_info) { - Error error; - char exe_path[PATH_MAX]; - - PlatformSP host_platform_sp (Platform::GetHostPlatform ()); - - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - - FileSpec exe_spec(launch_info.GetExecutableFile()); - - FileSpec::FileType file_type = exe_spec.GetFileType(); - if (file_type != FileSpec::eFileTypeRegular) - { - lldb::ModuleSP exe_module_sp; - error = host_platform_sp->ResolveExecutable (exe_spec, - arch_spec, - exe_module_sp, - NULL); - - if (error.Fail()) - return error; - - if (exe_module_sp) - exe_spec = exe_module_sp->GetFileSpec(); - } - - if (exe_spec.Exists()) - { - exe_spec.GetPath (exe_path, sizeof(exe_path)); - } - else - { - launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); - return error; - } - - assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)); - - ::pid_t pid = LLDB_INVALID_PROCESS_ID; - - error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); + std::unique_ptr<ProcessLauncher> delegate_launcher; +#if defined(_WIN32) + delegate_launcher.reset(new ProcessLauncherWindows()); +#else + delegate_launcher.reset(new ProcessLauncherPosix()); +#endif + MonitoringProcessLauncher launcher(std::move(delegate_launcher)); - if (pid != LLDB_INVALID_PROCESS_ID) - { - // If all went well, then set the process ID into the launch info - launch_info.SetProcessID(pid); + Error error; + HostProcess process = launcher.LaunchProcess(launch_info, error); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + // TODO(zturner): It would be better if the entire HostProcess were returned instead of writing + // it into this structure. + launch_info.SetProcessID(process.GetProcessId()); - // Make sure we reap any processes we spawn or we will have zombies. - if (!launch_info.MonitorProcess()) - { - const bool monitor_signals = false; - StartMonitoringChildProcess (Process::SetProcessExitStatus, - NULL, - pid, - monitor_signals); - if (log) - log->PutCString ("monitored child process with default Process::SetProcessExitStatus."); - } - else - { - if (log) - log->PutCString ("monitored child process with user-specified process monitor."); - } - } - else - { - // Invalid process ID, something didn't go well - if (error.Success()) - error.SetErrorString ("process launch failed for unknown reasons"); - } return error; } diff --git a/lldb/source/Host/common/HostProcess.cpp b/lldb/source/Host/common/HostProcess.cpp index 9339d37b912..58a214693a5 100644 --- a/lldb/source/Host/common/HostProcess.cpp +++ b/lldb/source/Host/common/HostProcess.cpp @@ -9,6 +9,7 @@ #include "lldb/Host/HostNativeProcess.h" #include "lldb/Host/HostProcess.h" +#include "lldb/Host/HostThread.h" using namespace lldb; using namespace lldb_private; @@ -47,6 +48,12 @@ bool HostProcess::IsRunning() const return m_native_process->IsRunning(); } +HostThread +HostProcess::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) +{ + return m_native_process->StartMonitoring(callback, callback_baton, monitor_signals); +} + HostNativeProcessBase &HostProcess::GetNativeProcess() { return *m_native_process; diff --git a/lldb/source/Host/common/MonitoringProcessLauncher.cpp b/lldb/source/Host/common/MonitoringProcessLauncher.cpp new file mode 100644 index 00000000000..3b0078474b0 --- /dev/null +++ b/lldb/source/Host/common/MonitoringProcessLauncher.cpp @@ -0,0 +1,102 @@ +//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +using namespace lldb; +using namespace lldb_private; + +MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher) + : m_delegate_launcher(std::move(delegate_launcher)) +{ +} + +HostProcess +MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) +{ + ProcessLaunchInfo resolved_info(launch_info); + + error.Clear(); + char exe_path[PATH_MAX]; + + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + + const ArchSpec &arch_spec = resolved_info.GetArchitecture(); + + FileSpec exe_spec(resolved_info.GetExecutableFile()); + + FileSpec::FileType file_type = exe_spec.GetFileType(); + if (file_type != FileSpec::eFileTypeRegular) + { + lldb::ModuleSP exe_module_sp; + error = host_platform_sp->ResolveExecutable(exe_spec, arch_spec, exe_module_sp, NULL); + + if (error.Fail()) + return HostProcess(); + + if (exe_module_sp) + exe_spec = exe_module_sp->GetFileSpec(); + } + + if (exe_spec.Exists()) + { + exe_spec.GetPath(exe_path, sizeof(exe_path)); + } + else + { + resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + return HostProcess(); + } + + resolved_info.SetExecutableFile(exe_spec, false); + assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); + + ::pid_t pid = LLDB_INVALID_PROCESS_ID; + + HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); + + if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); + + void *baton = nullptr; + bool monitor_signals = false; + if (callback) + { + // If the ProcessLaunchInfo specified a callback, use that. + baton = launch_info.GetMonitorProcessBaton(); + monitor_signals = launch_info.GetMonitorSignals(); + } + else + { + callback = Process::SetProcessExitStatus; + } + + process.StartMonitoring(callback, baton, monitor_signals); + if (log) + log->PutCString("started monitoring child process."); + } + else + { + // Invalid process ID, something didn't go well + if (error.Success()) + error.SetErrorString("process launch failed for unknown reasons"); + } + return process; +} diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index ffa4f849965..228305e0814 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -1138,7 +1138,7 @@ getXPCAuthorization (ProcessLaunchInfo &launch_info) #endif static Error -LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) +LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { #if !NO_XPC_SERVICES Error error = getXPCAuthorization(launch_info); @@ -1347,9 +1347,9 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) return error; #endif } - - ::pid_t pid = LLDB_INVALID_PROCESS_ID; - + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + if (ShouldLaunchUsingXPC(launch_info)) { error = LaunchProcessXPC(exe_path, launch_info, pid); diff --git a/lldb/source/Host/posix/HostProcessPosix.cpp b/lldb/source/Host/posix/HostProcessPosix.cpp index 0d9f85377dd..8e19add048e 100644 --- a/lldb/source/Host/posix/HostProcessPosix.cpp +++ b/lldb/source/Host/posix/HostProcessPosix.cpp @@ -1,4 +1,4 @@ -//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===// +//===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Host.h" #include "lldb/Host/posix/HostProcessPosix.h" #include "lldb/Host/FileSystem.h" @@ -107,3 +108,9 @@ bool HostProcessPosix::IsRunning() const Error error = Signal(0); return error.Success(); } + +HostThread +HostProcessPosix::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) +{ + return Host::StartMonitoringChildProcess(callback, callback_baton, m_process, monitor_signals); +} diff --git a/lldb/source/Host/posix/ProcessLauncherPosix.cpp b/lldb/source/Host/posix/ProcessLauncherPosix.cpp new file mode 100644 index 00000000000..dd5c5121a97 --- /dev/null +++ b/lldb/source/Host/posix/ProcessLauncherPosix.cpp @@ -0,0 +1,33 @@ +//===-- ProcessLauncherPosix.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Host.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/posix/ProcessLauncherPosix.h" + +#include "lldb/Target/ProcessLaunchInfo.h" + +#include <limits.h> + +using namespace lldb; +using namespace lldb_private; + +HostProcess +ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) +{ + lldb::pid_t pid; + char exe_path[PATH_MAX]; + + launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + + // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this + // ProcessLauncher when it wants a posix_spawn launch. + error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); + return HostProcess(pid); +} diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp index 4542025f6ee..4f698df16eb 100644 --- a/lldb/source/Host/windows/Host.cpp +++ b/lldb/source/Host/windows/Host.cpp @@ -96,14 +96,6 @@ namespace } } -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - Error error; - assert(!"Not implemented yet!!!"); - return error; -} - lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { diff --git a/lldb/source/Host/windows/HostProcessWindows.cpp b/lldb/source/Host/windows/HostProcessWindows.cpp index 447f672ac77..8388e21b853 100644 --- a/lldb/source/Host/windows/HostProcessWindows.cpp +++ b/lldb/source/Host/windows/HostProcessWindows.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/FileSpec.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/HostProcessWindows.h" @@ -17,6 +19,16 @@ using namespace lldb_private; +namespace +{ +struct MonitorInfo +{ + HostProcess::MonitorCallback callback; + void *baton; + HANDLE process_handle; +}; +} + HostProcessWindows::HostProcessWindows() : HostNativeProcessBase() { @@ -61,7 +73,7 @@ Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const lldb::pid_t HostProcessWindows::GetProcessId() const { - return ::GetProcessId(m_process); + return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); } bool HostProcessWindows::IsRunning() const @@ -76,9 +88,42 @@ bool HostProcessWindows::IsRunning() const return (code == STILL_ACTIVE); } +HostThread +HostProcessWindows::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) +{ + HostThread monitor_thread; + MonitorInfo *info = new MonitorInfo; + info->callback = callback; + info->baton = callback_baton; + + // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that + // the monitor thread can have ownership over its own copy of the handle. + HostThread result; + if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); + return result; +} + +lldb::thread_result_t +HostProcessWindows::MonitorThread(void *thread_arg) +{ + DWORD exit_code; + + MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); + if (info) + { + DWORD wait_result = ::WaitForSingleObject(info->process_handle, INFINITE); + ::GetExitCodeProcess(info->process_handle, &exit_code); + info->callback(info->baton, ::GetProcessId(info->process_handle), true, 0, exit_code); + + delete (info); + } + return 0; +} + void HostProcessWindows::Close() { - if (m_process != nullptr) + if (m_process != LLDB_INVALID_PROCESS) ::CloseHandle(m_process); m_process = nullptr; } diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp new file mode 100644 index 00000000000..7a99e0944e5 --- /dev/null +++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp @@ -0,0 +1,94 @@ +//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/windows/ProcessLauncherWindows.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +#include <string> +#include <vector> + +using namespace lldb; +using namespace lldb_private; + +HostProcess +ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) +{ + error.Clear(); + + std::string executable; + std::string commandLine; + 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, TRUE, CREATE_NEW_CONSOLE, NULL, + launch_info.GetWorkingDirectory(), &startupinfo, &pi); + if (result) + { + // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. + ::CloseHandle(pi.hThread); + } + + if (stdin_handle) + ::CloseHandle(stdin_handle); + if (stdout_handle) + ::CloseHandle(stdout_handle); + if (stderr_handle) + ::CloseHandle(stderr_handle); + + if (!result) + error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(pi.hProcess); +} + +HANDLE +ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) +{ + const 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; +} |