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

Side by Side Diff: client/crashpad_client_mac.cc

Issue 1408473002: ChildPortHandshake: allow receive rights to be received (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 5 years, 1 month 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 | « no previous file | handler/main.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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 const base::FilePath& handler, 90 const base::FilePath& handler,
91 const base::FilePath& database, 91 const base::FilePath& database,
92 const std::string& url, 92 const std::string& url,
93 const std::map<std::string, std::string>& annotations, 93 const std::map<std::string, std::string>& annotations,
94 const std::vector<std::string>& arguments) { 94 const std::vector<std::string>& arguments) {
95 DCHECK(!exception_port_.is_valid()); 95 DCHECK(!exception_port_.is_valid());
96 96
97 // Set up the arguments for execve() first. These aren’t needed until execve() 97 // Set up the arguments for execve() first. These aren’t needed until execve()
98 // is called, but it’s dangerous to do this in a child process after fork(). 98 // is called, but it’s dangerous to do this in a child process after fork().
99 ChildPortHandshake child_port_handshake; 99 ChildPortHandshake child_port_handshake;
100 int handshake_fd = child_port_handshake.ReadPipeFD(); 100 base::ScopedFD client_read_fd = child_port_handshake.ClientReadFD();
101 101
102 // Use handler as argv[0], followed by arguments directed by this method’s 102 // Use handler as argv[0], followed by arguments directed by this method’s
103 // parameters and a --handshake-fd argument. |arguments| are added first so 103 // parameters and a --handshake-fd argument. |arguments| are added first so
104 // that if it erroneously contains an argument such as --url, the actual |url| 104 // that if it erroneously contains an argument such as --url, the actual |url|
105 // argument passed to this method will supersede it. In normal command-line 105 // argument passed to this method will supersede it. In normal command-line
106 // processing, the last parameter wins in the case of a conflict. 106 // processing, the last parameter wins in the case of a conflict.
107 std::vector<std::string> argv(1, handler.value()); 107 std::vector<std::string> argv(1, handler.value());
108 argv.reserve(1 + arguments.size() + 2 + annotations.size() + 1); 108 argv.reserve(1 + arguments.size() + 2 + annotations.size() + 1);
109 for (const std::string& argument : arguments) { 109 for (const std::string& argument : arguments) {
110 argv.push_back(argument); 110 argv.push_back(argument);
111 } 111 }
112 if (!database.value().empty()) { 112 if (!database.value().empty()) {
113 argv.push_back(FormatArgumentString("database", database.value())); 113 argv.push_back(FormatArgumentString("database", database.value()));
114 } 114 }
115 if (!url.empty()) { 115 if (!url.empty()) {
116 argv.push_back(FormatArgumentString("url", url)); 116 argv.push_back(FormatArgumentString("url", url));
117 } 117 }
118 for (const auto& kv : annotations) { 118 for (const auto& kv : annotations) {
119 argv.push_back( 119 argv.push_back(
120 FormatArgumentString("annotation", kv.first + '=' + kv.second)); 120 FormatArgumentString("annotation", kv.first + '=' + kv.second));
121 } 121 }
122 argv.push_back(FormatArgumentInt("handshake-fd", handshake_fd)); 122 argv.push_back(FormatArgumentInt("handshake-fd", client_read_fd.get()));
123 123
124 // argv_c contains const char* pointers and is terminated by nullptr. argv 124 // argv_c contains const char* pointers and is terminated by nullptr. argv
125 // is required because the pointers in argv_c need to point somewhere, and 125 // is required because the pointers in argv_c need to point somewhere, and
126 // they can’t point to temporaries such as those returned by 126 // they can’t point to temporaries such as those returned by
127 // FormatArgumentString(). 127 // FormatArgumentString().
128 std::vector<const char*> argv_c; 128 std::vector<const char*> argv_c;
129 argv_c.reserve(argv.size() + 1); 129 argv_c.reserve(argv.size() + 1);
130 for (const std::string& argument : argv) { 130 for (const std::string& argument : argv) {
131 argv_c.push_back(argument.c_str()); 131 argv_c.push_back(argument.c_str());
132 } 132 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 174
175 if (pid > 0) { 175 if (pid > 0) {
176 // Child process. 176 // Child process.
177 177
178 // _exit() instead of exit(), because fork() was called. 178 // _exit() instead of exit(), because fork() was called.
179 _exit(EXIT_SUCCESS); 179 _exit(EXIT_SUCCESS);
180 } 180 }
181 181
182 // Grandchild process. 182 // Grandchild process.
183 183
184 CloseMultipleNowOrOnExec(STDERR_FILENO + 1, handshake_fd); 184 CloseMultipleNowOrOnExec(STDERR_FILENO + 1, client_read_fd.get());
185 185
186 // &argv_c[0] is a pointer to a pointer to const char data, but because of 186 // &argv_c[0] is a pointer to a pointer to const char data, but because of
187 // how C (not C++) works, execvp() wants a pointer to a const pointer to 187 // how C (not C++) works, execvp() wants a pointer to a const pointer to
188 // char data. It modifies neither the data nor the pointers, so the 188 // char data. It modifies neither the data nor the pointers, so the
189 // const_cast is safe. 189 // const_cast is safe.
190 execvp(handler.value().c_str(), const_cast<char* const*>(&argv_c[0])); 190 execvp(handler.value().c_str(), const_cast<char* const*>(&argv_c[0]));
191 PLOG(FATAL) << "execvp " << handler.value(); 191 PLOG(FATAL) << "execvp " << handler.value();
192 } 192 }
193 193
194 // Parent process. 194 // Parent process.
195 195
196 client_read_fd.reset();
197
196 // waitpid() for the child, so that it does not become a zombie process. The 198 // waitpid() for the child, so that it does not become a zombie process. The
197 // child normally exits quickly. 199 // child normally exits quickly.
198 int status; 200 int status;
199 pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0)); 201 pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0));
200 PCHECK(wait_pid != -1) << "waitpid"; 202 PCHECK(wait_pid != -1) << "waitpid";
201 DCHECK_EQ(wait_pid, pid); 203 DCHECK_EQ(wait_pid, pid);
202 204
203 if (WIFSIGNALED(status)) { 205 if (WIFSIGNALED(status)) {
204 LOG(WARNING) << "intermediate process: signal " << WTERMSIG(status); 206 LOG(WARNING) << "intermediate process: signal " << WTERMSIG(status);
205 } else if (!WIFEXITED(status)) { 207 } else if (!WIFEXITED(status)) {
206 DLOG(WARNING) << "intermediate process: unknown termination " << status; 208 DLOG(WARNING) << "intermediate process: unknown termination " << status;
207 } else if (WEXITSTATUS(status) != EXIT_SUCCESS) { 209 } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
208 LOG(WARNING) << "intermediate process: exit status " << WEXITSTATUS(status); 210 LOG(WARNING) << "intermediate process: exit status " << WEXITSTATUS(status);
209 } 211 }
210 212
211 // Rendezvous with the handler running in the grandchild process. 213 // Rendezvous with the handler running in the grandchild process.
212 exception_port_.reset(child_port_handshake.RunServer()); 214 exception_port_.reset(child_port_handshake.RunServer(
215 ChildPortHandshake::PortRightType::kSendRight));
213 216
214 return exception_port_.is_valid(); 217 return exception_port_.is_valid();
215 } 218 }
216 219
217 bool CrashpadClient::UseHandler() { 220 bool CrashpadClient::UseHandler() {
218 DCHECK(exception_port_.is_valid()); 221 DCHECK(exception_port_.is_valid());
219 222
220 return SetCrashExceptionPorts(exception_port_.get()); 223 return SetCrashExceptionPorts(exception_port_.get());
221 } 224 }
222 225
223 // static 226 // static
224 void CrashpadClient::UseSystemDefaultHandler() { 227 void CrashpadClient::UseSystemDefaultHandler() {
225 base::mac::ScopedMachSendRight 228 base::mac::ScopedMachSendRight
226 system_crash_reporter_handler(SystemCrashReporterHandler()); 229 system_crash_reporter_handler(SystemCrashReporterHandler());
227 230
228 // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL 231 // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL
229 // to clear the current exception ports. 232 // to clear the current exception ports.
230 if (!SetCrashExceptionPorts(system_crash_reporter_handler.get())) { 233 if (!SetCrashExceptionPorts(system_crash_reporter_handler.get())) {
231 SetCrashExceptionPorts(MACH_PORT_NULL); 234 SetCrashExceptionPorts(MACH_PORT_NULL);
232 } 235 }
233 } 236 }
234 237
235 } // namespace crashpad 238 } // namespace crashpad
OLDNEW
« no previous file with comments | « no previous file | handler/main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698