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

Side by Side 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: . 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/test/multiprocess_exec.h"
16
17 #include "base/logging.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "gtest/gtest.h"
20
21 namespace crashpad {
22 namespace test {
23
24 namespace {
25
26 void ArgvQuote(const std::wstring& argument, std::wstring* command_line) {
Mark Mentovai 2015/01/28 19:58:28 It’s not obvious that this is additive. Add a comm
scottmg 2015/01/28 22:14:58 Done.
27 // Don't bother quoting if unnecessary.
28 if (argument.empty() == false &&
Mark Mentovai 2015/01/28 19:58:28 Adapt to local style: !argument.empty(), std::wstr
scottmg 2015/01/28 22:14:58 Done.
29 argument.find_first_of(L" \t\n\v\"") == argument.npos) {
30 command_line->append(argument);
31 } else {
32 // Ref: http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04 /23/everyone-quotes-arguments-the-wrong-way.aspx
Mark Mentovai 2015/01/28 19:58:28 I’m glad you did this correctly. Sloppy quoting is
Mark Mentovai 2015/01/28 19:58:28 Promote this to the function-level comment?
scottmg 2015/01/28 22:14:58 Done.
33 command_line->push_back(L'"');
34 for (std::wstring::const_iterator i = argument.begin();; ++i) {
35 unsigned backslash_count = 0;
Mark Mentovai 2015/01/28 19:58:28 size_t
scottmg 2015/01/28 22:14:58 Done.
36 while (i != argument.end() && *i == L'\\') {
37 ++i;
38 ++backslash_count;
39 }
40 if (i == argument.end()) {
41 // Escape all backslashes, but let the terminating double quotation mark
42 // we add below be interpreted as a metacharacter.
43 command_line->append(backslash_count * 2, L'\\');
44 break;
45 } else if (*i == L'"') {
46 // Escape all backslashes and the following double quotation mark.
47 command_line->append(backslash_count * 2 + 1, L'\\');
48 command_line->push_back(*i);
49 } else {
50 // Backslashes aren't special here.
51 command_line->append(backslash_count, L'\\');
52 command_line->push_back(*i);
53 }
54 }
55 command_line->push_back(L'"');
56 }
57 }
58
59 } // namespace
60
61 namespace internal {
62
63 struct MultiprocessInfo {
64 MultiprocessInfo() {}
65 ScopedFileHANDLE pipe_c2p_read;
66 ScopedFileHANDLE pipe_c2p_write;
67 ScopedFileHANDLE pipe_p2c_read;
68 ScopedFileHANDLE pipe_p2c_write;
69 PROCESS_INFORMATION process_info;
70 };
71
72 } // namespace internal
73
74 Multiprocess::Multiprocess()
Mark Mentovai 2015/01/28 19:58:28 There should be a comment somewhere (maybe here, m
scottmg 2015/01/28 22:14:58 Done in header.
75 : info_(nullptr),
76 code_(EXIT_SUCCESS),
77 reason_(kTerminationNormal) {
78 }
79
80 void Multiprocess::Run() {
81 ASSERT_NO_FATAL_FAILURE(PreFork());
82 RunChild();
Mark Mentovai 2015/01/28 19:58:28 To that end, this whole function is kind of weird.
scottmg 2015/01/28 22:14:58 It's setting up and spawning the child, then runni
Mark Mentovai 2015/01/28 22:32:54 scottmg wrote:
83 RunParent();
84
85 // Reap the child.
86 WaitForSingleObject(info_->process_info.hProcess, INFINITE);
87 CloseHandle(info_->process_info.hThread);
88 CloseHandle(info_->process_info.hProcess);
89 }
90
91 Multiprocess::~Multiprocess() {
92 delete info_;
93 }
94
95 void Multiprocess::PreFork() {
96 NOTREACHED();
97 }
98
99 FileHandle Multiprocess::ReadPipeHandle() const {
100 // This is the parent case, it's stdin in the child.
101 return info_->pipe_c2p_read.get();
102 }
103
104 FileHandle Multiprocess::WritePipeHandle() const {
105 // This is the parent case, it's stdout in the child.
106 return info_->pipe_p2c_write.get();
107 }
108
Mark Mentovai 2015/01/28 19:58:28 You haven’t implemented ChildPID() (but you probab
scottmg 2015/01/28 22:14:58 Done.
109 void Multiprocess::RunParent() {
110 MultiprocessParent();
111
112 info_->pipe_c2p_read.reset();
113 info_->pipe_p2c_write.reset();
114 }
115
116 void Multiprocess::RunChild() {
117 MultiprocessChild();
118
119 info_->pipe_c2p_write.reset();
120 info_->pipe_p2c_read.reset();
121 }
122
123 MultiprocessExec::MultiprocessExec()
124 : Multiprocess(), command_(), arguments_(), argv_() {
125 }
126
127 void MultiprocessExec::SetChildCommand(
128 const std::string& command,
129 const std::vector<std::string>* arguments) {
130 command_ = command;
131 if (arguments) {
132 arguments_ = *arguments;
133 } else {
134 arguments_.clear();
135 }
136 }
137
138 MultiprocessExec::~MultiprocessExec() {
139 }
140
141 void MultiprocessExec::PreFork() {
142 ASSERT_FALSE(command_.empty());
143
144 argv_.clear();
145 ArgvQuote(base::UTF8ToUTF16(command_), &argv_);
146 for (size_t i = 0; i < arguments_.size(); ++i) {
147 argv_ += L" ";
148 ArgvQuote(base::UTF8ToUTF16(arguments_[i]), &argv_);
149 }
150
151 // Make pipes for child-to-parent and parent-to-child communication. Mark them
152 // as inheritable via the SECURITY_ATTRIBUTES, but use SetHandleInformation to
153 // ensure that the parent sides are not inherited.
154 ASSERT_EQ(nullptr, info());
155 set_info(new internal::MultiprocessInfo);
Mark Mentovai 2015/01/28 19:58:28 () to be explicit.
scottmg 2015/01/28 22:14:58 Done.
156
157 SECURITY_ATTRIBUTES security_attributes = {0};
158 security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
159 security_attributes.bInheritHandle = TRUE;
160
161 HANDLE c2p_read, c2p_write;
162 PCHECK(CreatePipe(&c2p_read, &c2p_write, &security_attributes, 0));
163 PCHECK(SetHandleInformation(c2p_read, HANDLE_FLAG_INHERIT, 0));
164 info()->pipe_c2p_read.reset(c2p_read);
165 info()->pipe_c2p_write.reset(c2p_write);
166
167 HANDLE p2c_read, p2c_write;
168 PCHECK(CreatePipe(&p2c_read, &p2c_write, &security_attributes, 0));
169 PCHECK(SetHandleInformation(p2c_write, HANDLE_FLAG_INHERIT, 0));
170 info()->pipe_p2c_read.reset(p2c_read);
171 info()->pipe_p2c_write.reset(p2c_write);
172 }
173
174 void MultiprocessExec::MultiprocessChild() {
175 STARTUPINFO startup_info = {0};
176 startup_info.cb = sizeof(startup_info);
177 startup_info.hStdInput = info()->pipe_p2c_read.get();
178 startup_info.hStdOutput = info()->pipe_c2p_write.get();
179 startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
180 startup_info.dwFlags = STARTF_USESTDHANDLES;
181 PCHECK(CreateProcess(base::UTF8ToUTF16(command_).c_str(),
182 &argv_[0], // This cannot be constant, per MSDN.
183 nullptr,
184 nullptr,
185 TRUE,
186 0,
187 nullptr,
188 nullptr,
189 &startup_info,
190 &info()->process_info));
191 }
192
193 } // namespace test
194 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698