| Index: runtime/bin/process_win.cc
|
| diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
|
| index 8d6b992f35776c86853d261d0099ff1ee0effa72..d57cde0afc98b77f9a4156156c3ebbc8ee71a7b1 100644
|
| --- a/runtime/bin/process_win.cc
|
| +++ b/runtime/bin/process_win.cc
|
| @@ -399,293 +399,329 @@ static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) {
|
| }
|
|
|
|
|
| -int Process::Start(const char* path,
|
| - char* arguments[],
|
| - intptr_t arguments_length,
|
| - const char* working_directory,
|
| - char* environment[],
|
| - intptr_t environment_length,
|
| - bool detach,
|
| - intptr_t* in,
|
| - intptr_t* out,
|
| - intptr_t* err,
|
| - intptr_t* id,
|
| - intptr_t* exit_handler,
|
| - char** os_error_message) {
|
| - HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
| - HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
| - HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
| - HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
| -
|
| - // Generate unique pipe names for the four named pipes needed.
|
| - wchar_t pipe_names[4][kMaxPipeNameSize];
|
| - int status = GenerateNames<4>(pipe_names);
|
| - if (status != 0) {
|
| - SetOsErrorMessage(os_error_message);
|
| - Log::PrintErr("UuidCreateSequential failed %d\n", status);
|
| - return status;
|
| - }
|
| +class ProcessStarter {
|
| + public:
|
| + ProcessStarter(const char* path,
|
| + char* arguments[],
|
| + intptr_t arguments_length,
|
| + const char* working_directory,
|
| + char* environment[],
|
| + intptr_t environment_length,
|
| + ProcessStartMode mode,
|
| + intptr_t* in,
|
| + intptr_t* out,
|
| + intptr_t* err,
|
| + intptr_t* id,
|
| + intptr_t* exit_handler,
|
| + char** os_error_message)
|
| + : path_(path),
|
| + working_directory_(working_directory),
|
| + mode_(mode),
|
| + in_(in),
|
| + out_(out),
|
| + err_(err),
|
| + id_(id),
|
| + exit_handler_(exit_handler),
|
| + os_error_message_(os_error_message) {
|
| + stdin_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
|
| + stdin_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
|
| + stdout_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
|
| + stdout_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
|
| + stderr_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
|
| + stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
|
| + exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
|
| + exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
|
| +
|
| + // Transform input strings to system format.
|
| + const wchar_t* system_path = StringUtils::Utf8ToWide(path_);
|
| + wchar_t** system_arguments = new wchar_t*[arguments_length];
|
| + for (int i = 0; i < arguments_length; i++) {
|
| + system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
|
| + }
|
|
|
| - if (!detach) {
|
| - // Open pipes for stdin, stdout, stderr and for communicating the exit
|
| - // code.
|
| - if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| + // Compute command-line length.
|
| + int command_line_length = wcslen(system_path);
|
| + for (int i = 0; i < arguments_length; i++) {
|
| + command_line_length += wcslen(system_arguments[i]);
|
| + }
|
| + // Account for null termination and one space per argument.
|
| + command_line_length += arguments_length + 1;
|
| +
|
| + // Put together command-line string.
|
| + command_line_ = new wchar_t[command_line_length];
|
| + int len = 0;
|
| + int remaining = command_line_length;
|
| + int written =
|
| + _snwprintf(command_line_ + len, remaining, L"%s", system_path);
|
| + len += written;
|
| + remaining -= written;
|
| + ASSERT(remaining >= 0);
|
| + for (int i = 0; i < arguments_length; i++) {
|
| + written =
|
| + _snwprintf(
|
| + command_line_ + len, remaining, L" %s", system_arguments[i]);
|
| + len += written;
|
| + remaining -= written;
|
| + ASSERT(remaining >= 0);
|
| }
|
| - } else {
|
| - // Open NUL for stdin, stdout and stderr.
|
| - stdin_handles[kReadHandle] = OpenNul();
|
| - if (stdin_handles[kReadHandle] == INVALID_HANDLE_VALUE) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - stdout_handles[kWriteHandle] = OpenNul();
|
| - if (stdout_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - stderr_handles[kWriteHandle] = OpenNul();
|
| - if (stderr_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - }
|
| -
|
| - // Setup info structures.
|
| - STARTUPINFOEXW startup_info;
|
| - ZeroMemory(&startup_info, sizeof(startup_info));
|
| - startup_info.StartupInfo.cb = sizeof(startup_info);
|
| - startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle];
|
| - startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle];
|
| - startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle];
|
| - startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
| -
|
| - LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = NULL;
|
| -
|
| - bool supports_proc_thread_attr_lists = EnsureInitialized();
|
| - if (supports_proc_thread_attr_lists) {
|
| - // Setup the handles to inherit. We only want to inherit the three handles
|
| - // for stdin, stdout and stderr.
|
| - SIZE_T size = 0;
|
| - // The call to determine the size of an attribute list always fails with
|
| - // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
|
| - if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
|
| - GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - attribute_list =
|
| - reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
|
| - ZeroMemory(attribute_list, size);
|
| - if (!init_proc_thread_attr_list(attribute_list, 1, 0, &size)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - free(attribute_list);
|
| - return error_code;
|
| - }
|
| - static const int kNumInheritedHandles = 3;
|
| - HANDLE inherited_handles[kNumInheritedHandles] =
|
| - { stdin_handles[kReadHandle],
|
| - stdout_handles[kWriteHandle],
|
| - stderr_handles[kWriteHandle] };
|
| - if (!update_proc_thread_attr(attribute_list,
|
| - 0,
|
| - PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
| - inherited_handles,
|
| - kNumInheritedHandles * sizeof(HANDLE),
|
| - NULL,
|
| - NULL)) {
|
| - delete_proc_thread_attr_list(attribute_list);
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - free(attribute_list);
|
| - return error_code;
|
| - }
|
| - startup_info.lpAttributeList = attribute_list;
|
| - }
|
| -
|
| - PROCESS_INFORMATION process_info;
|
| - ZeroMemory(&process_info, sizeof(process_info));
|
| -
|
| - // Transform input strings to system format.
|
| - const wchar_t* system_path = StringUtils::Utf8ToWide(path);
|
| - wchar_t** system_arguments = new wchar_t*[arguments_length];
|
| - for (int i = 0; i < arguments_length; i++) {
|
| - system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
|
| - }
|
| -
|
| - // Compute command-line length.
|
| - int command_line_length = wcslen(system_path);
|
| - for (int i = 0; i < arguments_length; i++) {
|
| - command_line_length += wcslen(system_arguments[i]);
|
| - }
|
| - // Account for null termination and one space per argument.
|
| - command_line_length += arguments_length + 1;
|
| - static const int kMaxCommandLineLength = 32768;
|
| - if (command_line_length > kMaxCommandLineLength) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| free(const_cast<wchar_t*>(system_path));
|
| for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
|
| delete[] system_arguments;
|
| +
|
| + // Create environment block if an environment is supplied.
|
| + environment_block_ = NULL;
|
| + if (environment != NULL) {
|
| + wchar_t** system_environment = new wchar_t*[environment_length];
|
| + // Convert environment strings to system strings.
|
| + for (intptr_t i = 0; i < environment_length; i++) {
|
| + system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
|
| + }
|
| +
|
| + // An environment block is a sequence of zero-terminated strings
|
| + // followed by a block-terminating zero char.
|
| + intptr_t block_size = 1;
|
| + for (intptr_t i = 0; i < environment_length; i++) {
|
| + block_size += wcslen(system_environment[i]) + 1;
|
| + }
|
| + environment_block_ = new wchar_t[block_size];
|
| + intptr_t block_index = 0;
|
| + for (intptr_t i = 0; i < environment_length; i++) {
|
| + intptr_t len = wcslen(system_environment[i]);
|
| + intptr_t result = _snwprintf(environment_block_ + block_index,
|
| + len,
|
| + L"%s",
|
| + system_environment[i]);
|
| + ASSERT(result == len);
|
| + block_index += len;
|
| + environment_block_[block_index++] = '\0';
|
| + }
|
| + // Block-terminating zero char.
|
| + environment_block_[block_index++] = '\0';
|
| + ASSERT(block_index == block_size);
|
| + for (intptr_t i = 0; i < environment_length; i++) {
|
| + free(system_environment[i]);
|
| + }
|
| + delete[] system_environment;
|
| + }
|
| +
|
| + system_working_directory_ = NULL;
|
| + if (working_directory_ != NULL) {
|
| + system_working_directory_ = StringUtils::Utf8ToWide(working_directory_);
|
| + }
|
| +
|
| + attribute_list_ = NULL;
|
| + }
|
| +
|
| +
|
| + ~ProcessStarter() {
|
| + // Deallocate command-line and environment block strings.
|
| + delete[] command_line_;
|
| + delete[] environment_block_;
|
| + if (system_working_directory_ != NULL) {
|
| + free(const_cast<wchar_t*>(system_working_directory_));
|
| + }
|
| + if (attribute_list_ != NULL) {
|
| + delete_proc_thread_attr_list(attribute_list_);
|
| + free(attribute_list_);
|
| + }
|
| + }
|
| +
|
| +
|
| + int Start() {
|
| + // Create pipes required.
|
| + int err = CreatePipes();
|
| + if (err != 0) return err;
|
| +
|
| + // Setup info structures.
|
| + STARTUPINFOEXW startup_info;
|
| + ZeroMemory(&startup_info, sizeof(startup_info));
|
| + startup_info.StartupInfo.cb = sizeof(startup_info);
|
| + startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle];
|
| + startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle];
|
| + startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle];
|
| + startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
| +
|
| + bool supports_proc_thread_attr_lists = EnsureInitialized();
|
| if (supports_proc_thread_attr_lists) {
|
| - delete_proc_thread_attr_list(attribute_list);
|
| - free(attribute_list);
|
| + // Setup the handles to inherit. We only want to inherit the three handles
|
| + // for stdin, stdout and stderr.
|
| + SIZE_T size = 0;
|
| + // The call to determine the size of an attribute list always fails with
|
| + // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
|
| + if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
|
| + GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + attribute_list_ =
|
| + reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
|
| + ZeroMemory(attribute_list_, size);
|
| + if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + static const int kNumInheritedHandles = 3;
|
| + HANDLE inherited_handles[kNumInheritedHandles] =
|
| + { stdin_handles_[kReadHandle],
|
| + stdout_handles_[kWriteHandle],
|
| + stderr_handles_[kWriteHandle] };
|
| + if (!update_proc_thread_attr(attribute_list_,
|
| + 0,
|
| + PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
| + inherited_handles,
|
| + kNumInheritedHandles * sizeof(HANDLE),
|
| + NULL,
|
| + NULL)) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + startup_info.lpAttributeList = attribute_list_;
|
| }
|
| - return error_code;
|
| +
|
| + PROCESS_INFORMATION process_info;
|
| + ZeroMemory(&process_info, sizeof(process_info));
|
| +
|
| + // Create process.
|
| + DWORD creation_flags =
|
| + EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
|
| + if (mode_ != kNormal) {
|
| + creation_flags |= DETACHED_PROCESS;
|
| + }
|
| + BOOL result = CreateProcessW(NULL, // ApplicationName
|
| + command_line_,
|
| + NULL, // ProcessAttributes
|
| + NULL, // ThreadAttributes
|
| + TRUE, // InheritHandles
|
| + creation_flags,
|
| + environment_block_,
|
| + system_working_directory_,
|
| + reinterpret_cast<STARTUPINFOW*>(&startup_info),
|
| + &process_info);
|
| +
|
| + if (result == 0) {
|
| + return CleanupAndReturnError();
|
| + }
|
| +
|
| + CloseHandle(stdin_handles_[kReadHandle]);
|
| + CloseHandle(stdout_handles_[kWriteHandle]);
|
| + CloseHandle(stderr_handles_[kWriteHandle]);
|
| + if (mode_ == kNormal) {
|
| + ProcessInfoList::AddProcess(process_info.dwProcessId,
|
| + process_info.hProcess,
|
| + exit_handles_[kWriteHandle]);
|
| + }
|
| + if (mode_ != kDetached) {
|
| + // Connect the three stdio streams.
|
| + FileHandle* stdin_handle = new FileHandle(stdin_handles_[kWriteHandle]);
|
| + FileHandle* stdout_handle = new FileHandle(stdout_handles_[kReadHandle]);
|
| + FileHandle* stderr_handle = new FileHandle(stderr_handles_[kReadHandle]);
|
| + *in_ = reinterpret_cast<intptr_t>(stdout_handle);
|
| + *out_ = reinterpret_cast<intptr_t>(stdin_handle);
|
| + *err_ = reinterpret_cast<intptr_t>(stderr_handle);
|
| + if (mode_ == kNormal) {
|
| + FileHandle* exit_handle = new FileHandle(exit_handles_[kReadHandle]);
|
| + *exit_handler_ = reinterpret_cast<intptr_t>(exit_handle);
|
| + }
|
| + }
|
| +
|
| + CloseHandle(process_info.hThread);
|
| +
|
| + // Return process id.
|
| + *id_ = process_info.dwProcessId;
|
| + return 0;
|
| }
|
|
|
| - // Put together command-line string.
|
| - wchar_t* command_line = new wchar_t[command_line_length];
|
| - int len = 0;
|
| - int remaining = command_line_length;
|
| - int written = _snwprintf(command_line + len, remaining, L"%s", system_path);
|
| - len += written;
|
| - remaining -= written;
|
| - ASSERT(remaining >= 0);
|
| - for (int i = 0; i < arguments_length; i++) {
|
| - written =
|
| - _snwprintf(command_line + len, remaining, L" %s", system_arguments[i]);
|
| - len += written;
|
| - remaining -= written;
|
| - ASSERT(remaining >= 0);
|
| +
|
| + int CreatePipes() {
|
| + // Generate unique pipe names for the four named pipes needed.
|
| + wchar_t pipe_names[4][kMaxPipeNameSize];
|
| + int status = GenerateNames<4>(pipe_names);
|
| + if (status != 0) {
|
| + SetOsErrorMessage(os_error_message_);
|
| + Log::PrintErr("UuidCreateSequential failed %d\n", status);
|
| + return status;
|
| + }
|
| +
|
| + if (mode_ != kDetached) {
|
| + // Open pipes for stdin, stdout, stderr and for communicating the exit
|
| + // code.
|
| + if (!CreateProcessPipe(stdin_handles_, pipe_names[0], kInheritRead) ||
|
| + !CreateProcessPipe(stdout_handles_, pipe_names[1], kInheritWrite) ||
|
| + !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + // Only open exit code pipe for non detached processes.
|
| + if (mode_ == kNormal) {
|
| + if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + }
|
| + } else {
|
| + // Open NUL for stdin, stdout and stderr.
|
| + if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
|
| + (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
|
| + (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) {
|
| + return CleanupAndReturnError();
|
| + }
|
| + }
|
| + return 0;
|
| }
|
| - free(const_cast<wchar_t*>(system_path));
|
| - for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
|
| - delete[] system_arguments;
|
| -
|
| - // Create environment block if an environment is supplied.
|
| - wchar_t* environment_block = NULL;
|
| - if (environment != NULL) {
|
| - wchar_t** system_environment = new wchar_t*[environment_length];
|
| - // Convert environment strings to system strings.
|
| - for (intptr_t i = 0; i < environment_length; i++) {
|
| - system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
|
| - }
|
| -
|
| - // An environment block is a sequence of zero-terminated strings
|
| - // followed by a block-terminating zero char.
|
| - intptr_t block_size = 1;
|
| - for (intptr_t i = 0; i < environment_length; i++) {
|
| - block_size += wcslen(system_environment[i]) + 1;
|
| - }
|
| - environment_block = new wchar_t[block_size];
|
| - intptr_t block_index = 0;
|
| - for (intptr_t i = 0; i < environment_length; i++) {
|
| - intptr_t len = wcslen(system_environment[i]);
|
| - intptr_t result = _snwprintf(environment_block + block_index,
|
| - len,
|
| - L"%s",
|
| - system_environment[i]);
|
| - ASSERT(result == len);
|
| - block_index += len;
|
| - environment_block[block_index++] = '\0';
|
| - }
|
| - // Block-terminating zero char.
|
| - environment_block[block_index++] = '\0';
|
| - ASSERT(block_index == block_size);
|
| - for (intptr_t i = 0; i < environment_length; i++) {
|
| - free(system_environment[i]);
|
| - }
|
| - delete[] system_environment;
|
| - }
|
| -
|
| - const wchar_t* system_working_directory = NULL;
|
| - if (working_directory != NULL) {
|
| - system_working_directory = StringUtils::Utf8ToWide(working_directory);
|
| - }
|
| -
|
| - // Create process.
|
| - DWORD creation_flags =
|
| - EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
|
| - if (detach) {
|
| - creation_flags |= DETACHED_PROCESS;
|
| - }
|
| - BOOL result = CreateProcessW(NULL, // ApplicationName
|
| - command_line,
|
| - NULL, // ProcessAttributes
|
| - NULL, // ThreadAttributes
|
| - TRUE, // InheritHandles
|
| - creation_flags,
|
| - environment_block,
|
| - system_working_directory,
|
| - reinterpret_cast<STARTUPINFOW*>(&startup_info),
|
| - &process_info);
|
| - // Deallocate command-line and environment block strings.
|
| - delete[] command_line;
|
| - delete[] environment_block;
|
| - if (system_working_directory != NULL) {
|
| - free(const_cast<wchar_t*>(system_working_directory));
|
| - }
|
| -
|
| - if (supports_proc_thread_attr_lists) {
|
| - delete_proc_thread_attr_list(attribute_list);
|
| - free(attribute_list);
|
| - }
|
| -
|
| - if (result == 0) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| +
|
| +
|
| + int CleanupAndReturnError() {
|
| + int error_code = SetOsErrorMessage(os_error_message_);
|
| CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + stdin_handles_, stdout_handles_, stderr_handles_, exit_handles_);
|
| return error_code;
|
| }
|
|
|
| - CloseHandle(stdin_handles[kReadHandle]);
|
| - CloseHandle(stdout_handles[kWriteHandle]);
|
| - CloseHandle(stderr_handles[kWriteHandle]);
|
| - if (!detach) {
|
| - ProcessInfoList::AddProcess(process_info.dwProcessId,
|
| - process_info.hProcess,
|
| - exit_handles[kWriteHandle]);
|
|
|
| - // Connect the three std streams.
|
| - FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
|
| - FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
|
| - FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
|
| - FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
|
| - *in = reinterpret_cast<intptr_t>(stdout_handle);
|
| - *out = reinterpret_cast<intptr_t>(stdin_handle);
|
| - *err = reinterpret_cast<intptr_t>(stderr_handle);
|
| - *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
|
| - }
|
| + HANDLE stdin_handles_[2];
|
| + HANDLE stdout_handles_[2];
|
| + HANDLE stderr_handles_[2];
|
| + HANDLE exit_handles_[2];
|
| +
|
| + const wchar_t* system_working_directory_;
|
| + wchar_t* command_line_;
|
| + wchar_t* environment_block_;
|
| + LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_;
|
| +
|
| + const char* path_;
|
| + const char* working_directory_;
|
| + ProcessStartMode mode_;
|
| + intptr_t* in_;
|
| + intptr_t* out_;
|
| + intptr_t* err_;
|
| + intptr_t* id_;
|
| + intptr_t* exit_handler_;
|
| + char** os_error_message_;
|
| +};
|
|
|
| - CloseHandle(process_info.hThread);
|
|
|
| - // Return process id.
|
| - *id = process_info.dwProcessId;
|
| - return 0;
|
| +int Process::Start(const char* path,
|
| + char* arguments[],
|
| + intptr_t arguments_length,
|
| + const char* working_directory,
|
| + char* environment[],
|
| + intptr_t environment_length,
|
| + ProcessStartMode mode,
|
| + intptr_t* in,
|
| + intptr_t* out,
|
| + intptr_t* err,
|
| + intptr_t* id,
|
| + intptr_t* exit_handler,
|
| + char** os_error_message) {
|
| + ProcessStarter starter(path,
|
| + arguments,
|
| + arguments_length,
|
| + working_directory,
|
| + environment,
|
| + environment_length,
|
| + mode,
|
| + in,
|
| + out,
|
| + err,
|
| + id,
|
| + exit_handler,
|
| + os_error_message);
|
| + return starter.Start();
|
| }
|
|
|
|
|
|
|