Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Unified Diff: util/test/multiprocess_exec_win.cc

Issue 880763002: Reorganize Multiprocess and implement for Windows (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: fixes 2 Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « util/test/multiprocess_exec_test_child.cc ('k') | util/test/multiprocess_posix.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: util/test/multiprocess_exec_win.cc
diff --git a/util/test/multiprocess_exec_win.cc b/util/test/multiprocess_exec_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..afd79b6046a869f70c8fe83aae4ecaee944aa4d7
--- /dev/null
+++ b/util/test/multiprocess_exec_win.cc
@@ -0,0 +1,206 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/test/multiprocess_exec.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "gtest/gtest.h"
+
+namespace crashpad {
+namespace test {
+
+namespace {
+
+// Ref: http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
+void AppendCommandLineArgument(const std::wstring& argument,
+ std::wstring* command_line) {
+ // Don't bother quoting if unnecessary.
+ if (!argument.empty() &&
+ argument.find_first_of(L" \t\n\v\"") == std::wstring::npos) {
+ command_line->append(argument);
+ } else {
+ command_line->push_back(L'"');
+ for (std::wstring::const_iterator i = argument.begin();; ++i) {
+ size_t backslash_count = 0;
+ while (i != argument.end() && *i == L'\\') {
+ ++i;
+ ++backslash_count;
+ }
+ if (i == argument.end()) {
+ // Escape all backslashes, but let the terminating double quotation mark
+ // we add below be interpreted as a metacharacter.
+ command_line->append(backslash_count * 2, L'\\');
+ break;
+ } else if (*i == L'"') {
+ // Escape all backslashes and the following double quotation mark.
+ command_line->append(backslash_count * 2 + 1, L'\\');
+ command_line->push_back(*i);
+ } else {
+ // Backslashes aren't special here.
+ command_line->append(backslash_count, L'\\');
+ command_line->push_back(*i);
+ }
+ }
+ command_line->push_back(L'"');
+ }
+}
+
+} // namespace
+
+namespace internal {
+
+struct MultiprocessInfo {
+ MultiprocessInfo() {}
+ ScopedFileHANDLE pipe_c2p_read;
+ ScopedFileHANDLE pipe_c2p_write;
+ ScopedFileHANDLE pipe_p2c_read;
+ ScopedFileHANDLE pipe_p2c_write;
+ PROCESS_INFORMATION process_info;
+};
+
+} // namespace internal
+
+Multiprocess::Multiprocess()
+ : info_(nullptr),
+ code_(EXIT_SUCCESS),
+ reason_(kTerminationNormal) {
+}
+
+void Multiprocess::Run() {
+ // Set up and spawn the child process.
+ ASSERT_NO_FATAL_FAILURE(PreFork());
+ RunChild();
+
+ // And then run the parent actions in this process.
+ RunParent();
+
+ // Reap the child.
+ WaitForSingleObject(info_->process_info.hProcess, INFINITE);
+ CloseHandle(info_->process_info.hThread);
+ CloseHandle(info_->process_info.hProcess);
+}
+
+Multiprocess::~Multiprocess() {
+ delete info_;
+}
+
+void Multiprocess::PreFork() {
+ NOTREACHED();
+}
+
+FileHandle Multiprocess::ReadPipeHandle() const {
+ // This is the parent case, it's stdin in the child.
+ return info_->pipe_c2p_read.get();
+}
+
+FileHandle Multiprocess::WritePipeHandle() const {
+ // This is the parent case, it's stdout in the child.
+ return info_->pipe_p2c_write.get();
+}
+
+void Multiprocess::CloseReadPipe() {
+ info_->pipe_c2p_read.reset();
+}
+
+void Multiprocess::CloseWritePipe() {
+ info_->pipe_p2c_write.reset();
+}
+
+void Multiprocess::RunParent() {
+ MultiprocessParent();
+
+ info_->pipe_c2p_read.reset();
+ info_->pipe_p2c_write.reset();
+}
+
+void Multiprocess::RunChild() {
+ MultiprocessChild();
+
+ info_->pipe_c2p_write.reset();
+ info_->pipe_p2c_read.reset();
+}
+
+MultiprocessExec::MultiprocessExec()
+ : Multiprocess(), command_(), arguments_(), command_line_() {
+}
+
+void MultiprocessExec::SetChildCommand(
+ const std::string& command,
+ const std::vector<std::string>* arguments) {
+ command_ = command;
+ if (arguments) {
+ arguments_ = *arguments;
+ } else {
+ arguments_.clear();
+ }
+}
+
+MultiprocessExec::~MultiprocessExec() {
+}
+
+void MultiprocessExec::PreFork() {
+ ASSERT_FALSE(command_.empty());
+
+ command_line_.clear();
+ AppendCommandLineArgument(base::UTF8ToUTF16(command_), &command_line_);
+ for (size_t i = 0; i < arguments_.size(); ++i) {
+ command_line_ += L" ";
+ AppendCommandLineArgument(base::UTF8ToUTF16(arguments_[i]), &command_line_);
+ }
+
+ // Make pipes for child-to-parent and parent-to-child communication. Mark them
+ // as inheritable via the SECURITY_ATTRIBUTES, but use SetHandleInformation to
+ // ensure that the parent sides are not inherited.
+ ASSERT_EQ(nullptr, info());
+ set_info(new internal::MultiprocessInfo());
+
+ SECURITY_ATTRIBUTES security_attributes = {0};
+ security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security_attributes.bInheritHandle = TRUE;
+
+ HANDLE c2p_read, c2p_write;
+ PCHECK(CreatePipe(&c2p_read, &c2p_write, &security_attributes, 0));
+ PCHECK(SetHandleInformation(c2p_read, HANDLE_FLAG_INHERIT, 0));
+ info()->pipe_c2p_read.reset(c2p_read);
+ info()->pipe_c2p_write.reset(c2p_write);
+
+ HANDLE p2c_read, p2c_write;
+ PCHECK(CreatePipe(&p2c_read, &p2c_write, &security_attributes, 0));
+ PCHECK(SetHandleInformation(p2c_write, HANDLE_FLAG_INHERIT, 0));
+ info()->pipe_p2c_read.reset(p2c_read);
+ info()->pipe_p2c_write.reset(p2c_write);
+}
+
+void MultiprocessExec::MultiprocessChild() {
+ STARTUPINFO startup_info = {0};
+ startup_info.cb = sizeof(startup_info);
+ startup_info.hStdInput = info()->pipe_p2c_read.get();
+ startup_info.hStdOutput = info()->pipe_c2p_write.get();
+ startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ PCHECK(CreateProcess(base::UTF8ToUTF16(command_).c_str(),
+ &command_line_[0], // This cannot be constant, per MSDN.
+ nullptr,
+ nullptr,
+ TRUE,
+ 0,
+ nullptr,
+ nullptr,
+ &startup_info,
+ &info()->process_info));
+}
+
+} // namespace test
+} // namespace crashpad
« no previous file with comments | « util/test/multiprocess_exec_test_child.cc ('k') | util/test/multiprocess_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698