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

Side by Side Diff: util/test/mac/mach_multiprocess.cc

Issue 491363002: Improvements for MachMultiprocess (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Add a pipe going in the other direction Created 6 years, 4 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
« no previous file with comments | « util/test/mac/mach_multiprocess.h ('k') | util/test/mac/mach_multiprocess_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 namespace crashpad { 60 namespace crashpad {
61 namespace test { 61 namespace test {
62 62
63 using namespace testing; 63 using namespace testing;
64 64
65 namespace internal { 65 namespace internal {
66 66
67 struct MachMultiprocessInfo { 67 struct MachMultiprocessInfo {
68 MachMultiprocessInfo() 68 MachMultiprocessInfo()
69 : service_name(), 69 : service_name(),
70 read_pipe(-1), 70 pipe_c2p_read(-1),
71 write_pipe(-1), 71 pipe_c2p_write(-1),
72 pipe_p2c_read(-1),
73 pipe_p2c_write(-1),
72 child_pid(0), 74 child_pid(0),
73 pipe_fd(-1), 75 read_pipe_fd(-1),
76 write_pipe_fd(-1),
74 local_port(MACH_PORT_NULL), 77 local_port(MACH_PORT_NULL),
75 remote_port(MACH_PORT_NULL), 78 remote_port(MACH_PORT_NULL),
76 child_task(MACH_PORT_NULL) {} 79 child_task(MACH_PORT_NULL) {}
77 80
78 std::string service_name; 81 std::string service_name;
79 base::ScopedFD read_pipe; 82 base::ScopedFD pipe_c2p_read; // child to parent
80 base::ScopedFD write_pipe; 83 base::ScopedFD pipe_c2p_write; // child to parent
84 base::ScopedFD pipe_p2c_read; // parent to child
85 base::ScopedFD pipe_p2c_write; // parent to child
81 pid_t child_pid; // valid only in parent 86 pid_t child_pid; // valid only in parent
82 int pipe_fd; // read_pipe in parent, write_pipe in child 87 int read_pipe_fd; // pipe_c2p_read in parent, pipe_p2c_read in child
88 int write_pipe_fd; // pipe_p2c_write in parent, pipe_c2p_write in child
83 base::mac::ScopedMachReceiveRight local_port; 89 base::mac::ScopedMachReceiveRight local_port;
84 base::mac::ScopedMachSendRight remote_port; 90 base::mac::ScopedMachSendRight remote_port;
85 base::mac::ScopedMachSendRight child_task; // valid only in parent 91 base::mac::ScopedMachSendRight child_task; // valid only in parent
86 }; 92 };
87 93
88 } // namespace internal 94 } // namespace internal
89 95
90 MachMultiprocess::MachMultiprocess() : info_(NULL) { 96 MachMultiprocess::MachMultiprocess() : info_(NULL) {
91 } 97 }
92 98
93 void MachMultiprocess::Run() { 99 void MachMultiprocess::Run() {
94 ASSERT_EQ(NULL, info_); 100 ASSERT_EQ(NULL, info_);
95 scoped_ptr<internal::MachMultiprocessInfo> info( 101 scoped_ptr<internal::MachMultiprocessInfo> info(
96 new internal::MachMultiprocessInfo); 102 new internal::MachMultiprocessInfo);
97 base::AutoReset<internal::MachMultiprocessInfo*> reset_info(&info_, 103 base::AutoReset<internal::MachMultiprocessInfo*> reset_info(&info_,
98 info.get()); 104 info.get());
99 105
100 int pipe_fds[2]; 106 int pipe_fds_c2p[2];
101 int rv = pipe(pipe_fds); 107 int rv = pipe(pipe_fds_c2p);
102 ASSERT_EQ(0, rv) << ErrnoMessage("pipe"); 108 ASSERT_EQ(0, rv) << ErrnoMessage("pipe");
103 109
104 info_->read_pipe.reset(pipe_fds[0]); 110 info_->pipe_c2p_read.reset(pipe_fds_c2p[0]);
105 info_->write_pipe.reset(pipe_fds[1]); 111 info_->pipe_c2p_write.reset(pipe_fds_c2p[1]);
112
113 int pipe_fds_p2c[2];
114 rv = pipe(pipe_fds_p2c);
115 ASSERT_EQ(0, rv) << ErrnoMessage("pipe");
116
117 info_->pipe_p2c_read.reset(pipe_fds_p2c[0]);
118 info_->pipe_p2c_write.reset(pipe_fds_p2c[1]);
106 119
107 // Set up the parent port and register it with the bootstrap server before 120 // Set up the parent port and register it with the bootstrap server before
108 // forking, so that it’s guaranteed to be there when the child attempts to 121 // forking, so that it’s guaranteed to be there when the child attempts to
109 // look it up. 122 // look it up.
110 info_->service_name = "com.googlecode.crashpad.test.mach_multiprocess."; 123 info_->service_name = "com.googlecode.crashpad.test.mach_multiprocess.";
111 for (int index = 0; index < 16; ++index) { 124 for (int index = 0; index < 16; ++index) {
112 info_->service_name.append(1, base::RandInt('A', 'Z')); 125 info_->service_name.append(1, base::RandInt('A', 'Z'));
113 } 126 }
114 127
115 mach_port_t local_port; 128 mach_port_t local_port;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 } 175 }
163 176
164 MachMultiprocess::~MachMultiprocess() { 177 MachMultiprocess::~MachMultiprocess() {
165 } 178 }
166 179
167 pid_t MachMultiprocess::ChildPID() const { 180 pid_t MachMultiprocess::ChildPID() const {
168 EXPECT_NE(0, info_->child_pid); 181 EXPECT_NE(0, info_->child_pid);
169 return info_->child_pid; 182 return info_->child_pid;
170 } 183 }
171 184
172 int MachMultiprocess::PipeFD() const { 185 int MachMultiprocess::ReadPipeFD() const {
173 EXPECT_NE(-1, info_->pipe_fd); 186 EXPECT_NE(-1, info_->read_pipe_fd);
174 return info_->pipe_fd; 187 return info_->read_pipe_fd;
188 }
189
190 int MachMultiprocess::WritePipeFD() const {
191 EXPECT_NE(-1, info_->write_pipe_fd);
192 return info_->write_pipe_fd;
175 } 193 }
176 194
177 mach_port_t MachMultiprocess::LocalPort() const { 195 mach_port_t MachMultiprocess::LocalPort() const {
178 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->local_port); 196 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->local_port);
179 return info_->local_port; 197 return info_->local_port;
180 } 198 }
181 199
182 mach_port_t MachMultiprocess::RemotePort() const { 200 mach_port_t MachMultiprocess::RemotePort() const {
183 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->remote_port); 201 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->remote_port);
184 return info_->remote_port; 202 return info_->remote_port;
185 } 203 }
186 204
187 mach_port_t MachMultiprocess::ChildTask() const { 205 mach_port_t MachMultiprocess::ChildTask() const {
188 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->child_task); 206 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), info_->child_task);
189 return info_->child_task; 207 return info_->child_task;
190 } 208 }
191 209
192 void MachMultiprocess::RunParent() { 210 void MachMultiprocess::RunParent() {
193 // The parent uses the read end of the pipe. 211 // The parent uses the read end of c2p and the write end of p2c.
194 info_->write_pipe.reset(); 212 info_->pipe_c2p_write.reset();
195 info_->pipe_fd = info_->read_pipe.get(); 213 info_->read_pipe_fd = info_->pipe_c2p_read.get();
214 info_->pipe_p2c_read.reset();
215 info_->write_pipe_fd = info_->pipe_p2c_write.get();
196 216
197 ReceiveHelloMessage message = {}; 217 ReceiveHelloMessage message = {};
198 218
199 kern_return_t kr = 219 kern_return_t kr =
200 mach_msg(&message.header, 220 mach_msg(&message.header,
201 MACH_RCV_MSG | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) | 221 MACH_RCV_MSG | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
202 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT), 222 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT),
203 0, 223 0,
204 sizeof(message), 224 sizeof(message),
205 info_->local_port, 225 info_->local_port,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 int mach_pid; 297 int mach_pid;
278 kr = pid_for_task(info_->child_task, &mach_pid); 298 kr = pid_for_task(info_->child_task, &mach_pid);
279 ASSERT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "pid_for_task"); 299 ASSERT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "pid_for_task");
280 ASSERT_EQ(ChildPID(), mach_pid); 300 ASSERT_EQ(ChildPID(), mach_pid);
281 301
282 Parent(); 302 Parent();
283 303
284 info_->remote_port.reset(); 304 info_->remote_port.reset();
285 info_->local_port.reset(); 305 info_->local_port.reset();
286 306
287 info_->pipe_fd = -1; 307 info_->read_pipe_fd = -1;
288 info_->read_pipe.reset(); 308 info_->pipe_c2p_read.reset();
309 info_->write_pipe_fd = -1;
310 info_->pipe_p2c_write.reset();
289 } 311 }
290 312
291 void MachMultiprocess::RunChild() { 313 void MachMultiprocess::RunChild() {
292 ScopedNotReached must_not_leave_this_scope; 314 ScopedNotReached must_not_leave_this_scope;
293 315
294 // local_port is not valid in the forked child process. 316 // local_port is not valid in the forked child process.
295 ignore_result(info_->local_port.release()); 317 ignore_result(info_->local_port.release());
296 318
297 // The child uses the write end of the pipe. 319 // The child uses the write end of c2p and the read end of p2c.
298 info_->read_pipe.reset(); 320 info_->pipe_c2p_read.reset();
299 info_->pipe_fd = info_->write_pipe.get(); 321 info_->write_pipe_fd = info_->pipe_c2p_write.get();
322 info_->pipe_p2c_write.reset();
323 info_->read_pipe_fd = info_->pipe_p2c_read.get();
300 324
301 mach_port_t local_port; 325 mach_port_t local_port;
302 kern_return_t kr = mach_port_allocate( 326 kern_return_t kr = mach_port_allocate(
303 mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &local_port); 327 mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &local_port);
304 ASSERT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_allocate"); 328 ASSERT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_allocate");
305 info_->local_port.reset(local_port); 329 info_->local_port.reset(local_port);
306 330
307 // The remote port can be obtained from the bootstrap server. 331 // The remote port can be obtained from the bootstrap server.
308 mach_port_t remote_port; 332 mach_port_t remote_port;
309 kr = bootstrap_look_up( 333 kr = bootstrap_look_up(
(...skipping 24 matching lines...) Expand all
334 MACH_PORT_NULL, 358 MACH_PORT_NULL,
335 MACH_MSG_TIMEOUT_NONE, 359 MACH_MSG_TIMEOUT_NONE,
336 MACH_PORT_NULL); 360 MACH_PORT_NULL);
337 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg"); 361 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg");
338 362
339 Child(); 363 Child();
340 364
341 info_->remote_port.reset(); 365 info_->remote_port.reset();
342 info_->local_port.reset(); 366 info_->local_port.reset();
343 367
344 info_->pipe_fd = -1; 368 info_->write_pipe_fd = -1;
345 info_->write_pipe.reset(); 369 info_->pipe_c2p_write.reset();
370 info_->read_pipe_fd = -1;
371 info_->pipe_p2c_read.reset();
346 372
347 if (Test::HasFailure()) { 373 if (Test::HasFailure()) {
348 // Trigger the ScopedNotReached destructor. 374 // Trigger the ScopedNotReached destructor.
349 return; 375 return;
350 } 376 }
351 377
352 exit(0); 378 exit(0);
353 } 379 }
354 380
355 } // namespace test 381 } // namespace test
356 } // namespace crashpad 382 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/test/mac/mach_multiprocess.h ('k') | util/test/mac/mach_multiprocess_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698