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

Side by Side Diff: util/test/multiprocess.cc

Issue 506143002: Refactor MachMultiprocess (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 6 years, 3 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/multiprocess.h ('k') | util/test/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
(Empty)
1 // Copyright 2014 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.h"
16
17 #include <signal.h>
18 #include <stdlib.h>
19 #include <sys/wait.h>
20
21 #include <string>
22
23 #include "base/auto_reset.h"
24 #include "base/files/scoped_file.h"
25 #include "base/memory/scoped_ptr.h"
26 #include "base/strings/stringprintf.h"
27 #include "gtest/gtest.h"
28 #include "util/misc/scoped_forbid_return.h"
29 #include "util/test/errors.h"
30
31 namespace crashpad {
32 namespace test {
33
34 using namespace testing;
35
36 namespace internal {
37
38 struct MultiprocessInfo {
39 MultiprocessInfo()
40 : pipe_c2p_read(-1),
41 pipe_c2p_write(-1),
42 pipe_p2c_read(-1),
43 pipe_p2c_write(-1),
44 child_pid(0) {}
45
46 base::ScopedFD pipe_c2p_read; // child to parent
47 base::ScopedFD pipe_c2p_write; // child to parent
48 base::ScopedFD pipe_p2c_read; // parent to child
49 base::ScopedFD pipe_p2c_write; // parent to child
50 pid_t child_pid; // valid only in parent
51 };
52
53 } // namespace internal
54
55 Multiprocess::Multiprocess() : info_(NULL) {
56 }
57
58 void Multiprocess::Run() {
59 ASSERT_EQ(NULL, info_);
60 scoped_ptr<internal::MultiprocessInfo> info(new internal::MultiprocessInfo);
61 base::AutoReset<internal::MultiprocessInfo*> reset_info(&info_, info.get());
62
63 PreFork();
64 if (testing::Test::HasFatalFailure()) {
65 return;
66 }
67
68 pid_t pid = fork();
69 ASSERT_GE(pid, 0) << ErrnoMessage("fork");
70
71 if (pid > 0) {
72 info_->child_pid = pid;
73
74 RunParent();
75
76 // Waiting for the child happens here instead of in RunParent() because even
77 // if RunParent() returns early due to a gtest fatal assertion failure, the
78 // child should still be reaped.
79
80 // This will make the parent hang up on the child as much as would be
81 // visible from the child’s perspective. The child’s side of the pipe will
82 // be broken, the child’s remote port will become a dead name, and an
83 // attempt by the child to look up the service will fail. If this weren’t
84 // done, the child might hang while waiting for a parent that has already
85 // triggered a fatal assertion failure to do something.
86 info.reset();
87 info_ = NULL;
88
89 int status;
90 pid_t wait_pid = waitpid(pid, &status, 0);
91 ASSERT_EQ(pid, wait_pid) << ErrnoMessage("waitpid");
92 if (status != 0) {
93 std::string message;
94 if (WIFEXITED(status)) {
95 message = base::StringPrintf("Child exited with code %d",
96 WEXITSTATUS(status));
97 } else if (WIFSIGNALED(status)) {
98 message = base::StringPrintf("Child terminated by signal %d (%s) %s",
99 WTERMSIG(status),
100 strsignal(WTERMSIG(status)),
101 WCOREDUMP(status) ? " (core dumped)" : "");
102 }
103 ASSERT_EQ(0, status) << message;
104 }
105 } else {
106 RunChild();
107 }
108 }
109
110 Multiprocess::~Multiprocess() {
111 }
112
113 void Multiprocess::PreFork() {
114 int pipe_fds_c2p[2];
115 int rv = pipe(pipe_fds_c2p);
116 ASSERT_EQ(0, rv) << ErrnoMessage("pipe");
117
118 info_->pipe_c2p_read.reset(pipe_fds_c2p[0]);
119 info_->pipe_c2p_write.reset(pipe_fds_c2p[1]);
120
121 int pipe_fds_p2c[2];
122 rv = pipe(pipe_fds_p2c);
123 ASSERT_EQ(0, rv) << ErrnoMessage("pipe");
124
125 info_->pipe_p2c_read.reset(pipe_fds_p2c[0]);
126 info_->pipe_p2c_write.reset(pipe_fds_p2c[1]);
127 }
128
129 pid_t Multiprocess::ChildPID() const {
130 EXPECT_NE(0, info_->child_pid);
131 return info_->child_pid;
132 }
133
134 int Multiprocess::ReadPipeFD() const {
135 int fd = info_->child_pid ? info_->pipe_c2p_read.get()
136 : info_->pipe_p2c_read.get();
137 EXPECT_NE(-1, fd);
138 return fd;
139 }
140
141 int Multiprocess::WritePipeFD() const {
142 int fd = info_->child_pid ? info_->pipe_p2c_write.get()
143 : info_->pipe_c2p_write.get();
144 EXPECT_NE(-1, fd);
145 return fd;
146 }
147
148 void Multiprocess::RunParent() {
149 // The parent uses the read end of c2p and the write end of p2c.
150 info_->pipe_c2p_write.reset();
151 info_->pipe_p2c_read.reset();
152
153 MultiprocessParent();
154
155 info_->pipe_c2p_read.reset();
156 info_->pipe_p2c_write.reset();
157 }
158
159 void Multiprocess::RunChild() {
160 ScopedForbidReturn forbid_return;
161
162 // The child uses the write end of c2p and the read end of p2c.
163 info_->pipe_c2p_read.reset();
164 info_->pipe_p2c_write.reset();
165
166 MultiprocessChild();
167
168 info_->pipe_c2p_write.reset();
169 info_->pipe_p2c_read.reset();
170
171 if (Test::HasFailure()) {
172 // Trigger the ScopedForbidReturn destructor.
173 return;
174 }
175
176 exit(0);
177 }
178
179 } // namespace test
180 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/test/multiprocess.h ('k') | util/test/multiprocess_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698