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

Side by Side Diff: util/win/exception_handler_server.cc

Issue 1432563003: win: crashpad_handler should create its own pipe name in ephemeral mode (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: --help 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 | « util/win/exception_handler_server.h ('k') | util/win/exception_handler_server_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 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 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 17 matching lines...) Expand all
28 #include "util/misc/tri_state.h" 28 #include "util/misc/tri_state.h"
29 #include "util/misc/uuid.h" 29 #include "util/misc/uuid.h"
30 #include "util/win/get_function.h" 30 #include "util/win/get_function.h"
31 #include "util/win/registration_protocol_win.h" 31 #include "util/win/registration_protocol_win.h"
32 #include "util/win/xp_compat.h" 32 #include "util/win/xp_compat.h"
33 33
34 namespace crashpad { 34 namespace crashpad {
35 35
36 namespace { 36 namespace {
37 37
38 // We create two pipe instances, so that there's one listening while the
39 // PipeServiceProc is processing a registration.
40 const size_t kPipeInstances = 2;
41
42 // Wraps CreateNamedPipe() to create a single named pipe instance.
43 //
44 // If first_instance is true, the named pipe instance will be created with
45 // FILE_FLAG_FIRST_PIPE_INSTANCE. This ensures that the the pipe name is not
46 // already in use when created.
47 HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name,
48 bool first_instance) {
49 return CreateNamedPipe(pipe_name.c_str(),
50 PIPE_ACCESS_DUPLEX |
51 (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE
52 : 0),
53 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
54 kPipeInstances,
55 512,
56 512,
57 0,
58 nullptr);
59 }
60
38 decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() { 61 decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() {
39 static const auto get_named_pipe_client_process_id = 62 static const auto get_named_pipe_client_process_id =
40 GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId); 63 GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId);
41 return get_named_pipe_client_process_id; 64 return get_named_pipe_client_process_id;
42 } 65 }
43 66
44 HANDLE DuplicateEvent(HANDLE process, HANDLE event) { 67 HANDLE DuplicateEvent(HANDLE process, HANDLE event) {
45 HANDLE handle; 68 HANDLE handle;
46 if (DuplicateHandle(GetCurrentProcess(), 69 if (DuplicateHandle(GetCurrentProcess(),
47 event, 70 event,
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 WinVMAddress debug_critical_section_address_; 250 WinVMAddress debug_critical_section_address_;
228 251
229 DISALLOW_COPY_AND_ASSIGN(ClientData); 252 DISALLOW_COPY_AND_ASSIGN(ClientData);
230 }; 253 };
231 254
232 } // namespace internal 255 } // namespace internal
233 256
234 ExceptionHandlerServer::Delegate::~Delegate() { 257 ExceptionHandlerServer::Delegate::~Delegate() {
235 } 258 }
236 259
237 ExceptionHandlerServer::ExceptionHandlerServer(const std::string& pipe_name, 260 ExceptionHandlerServer::ExceptionHandlerServer(bool persistent)
238 bool persistent) 261 : pipe_name_(),
239 : pipe_name_(pipe_name),
240 port_(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1)), 262 port_(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1)),
263 first_pipe_instance_(),
241 clients_lock_(), 264 clients_lock_(),
242 clients_(), 265 clients_(),
243 persistent_(persistent) { 266 persistent_(persistent) {
244 } 267 }
245 268
246 ExceptionHandlerServer::~ExceptionHandlerServer() { 269 ExceptionHandlerServer::~ExceptionHandlerServer() {
247 } 270 }
248 271
272 void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) {
273 DCHECK(pipe_name_.empty());
274 DCHECK(!pipe_name.empty());
275
276 pipe_name_ = pipe_name;
277 }
278
279 std::wstring ExceptionHandlerServer::CreatePipe() {
280 DCHECK(!first_pipe_instance_.is_valid());
281
282 int tries = 5;
283 std::string pipe_name_base =
284 base::StringPrintf("\\\\.\\pipe\\crashpad_%d_", GetCurrentProcessId());
285 std::wstring pipe_name;
286 do {
287 pipe_name = base::UTF8ToUTF16(pipe_name_base);
288 for (int index = 0; index < 16; ++index) {
289 pipe_name.append(1, static_cast<wchar_t>(base::RandInt('A', 'Z')));
290 }
291
292 first_pipe_instance_.reset(CreateNamedPipeInstance(pipe_name, true));
293
294 // CreateNamedPipe() is documented as setting the error to
295 // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the
296 // pipe name is already in use. However it may set the error to other codes
297 // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its
298 // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already
299 // exists and its attributes differ from those specified to
300 // CreateNamedPipe()). Some of these errors may be ambiguous: for example,
301 // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called
302 // incorrectly even in the absence of an existing pipe by the same name.
303 //
304 // Rather than chasing down all of the possible errors that might indicate
305 // that a pipe name is already in use, retry up to a few times on any error.
306 } while (!first_pipe_instance_.is_valid() && --tries);
307
308 PCHECK(first_pipe_instance_.is_valid()) << "CreateNamedPipe";
309
310 SetPipeName(pipe_name);
311 return pipe_name;
312 }
313
249 void ExceptionHandlerServer::Run(Delegate* delegate) { 314 void ExceptionHandlerServer::Run(Delegate* delegate) {
250 uint64_t shutdown_token = base::RandUint64(); 315 uint64_t shutdown_token = base::RandUint64();
251 // We create two pipe instances, so that there's one listening while the 316 ScopedKernelHANDLE thread_handles[kPipeInstances];
252 // PipeServiceProc is processing a registration.
253 ScopedKernelHANDLE thread_handles[2];
254 base::string16 pipe_name_16(base::UTF8ToUTF16(pipe_name_));
255 for (int i = 0; i < arraysize(thread_handles); ++i) { 317 for (int i = 0; i < arraysize(thread_handles); ++i) {
256 HANDLE pipe = 318 HANDLE pipe;
257 CreateNamedPipe(pipe_name_16.c_str(), 319 if (first_pipe_instance_.is_valid()) {
258 PIPE_ACCESS_DUPLEX, 320 pipe = first_pipe_instance_.release();
259 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 321 } else {
260 arraysize(thread_handles), 322 pipe = CreateNamedPipeInstance(pipe_name_, false);
261 512, 323 PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe";
262 512, 324 }
263 0,
264 nullptr);
265 PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe";
266 325
267 // Ownership of this object (and the pipe instance) is given to the new 326 // Ownership of this object (and the pipe instance) is given to the new
268 // thread. We close the thread handles at the end of the scope. They clean 327 // thread. We close the thread handles at the end of the scope. They clean
269 // up the context object and the pipe instance on termination. 328 // up the context object and the pipe instance on termination.
270 internal::PipeServiceContext* context = 329 internal::PipeServiceContext* context =
271 new internal::PipeServiceContext(port_.get(), 330 new internal::PipeServiceContext(port_.get(),
272 pipe, 331 pipe,
273 delegate, 332 delegate,
274 &clients_lock_, 333 &clients_lock_,
275 &clients_, 334 &clients_,
(...skipping 30 matching lines...) Expand all
306 break; 365 break;
307 } 366 }
308 367
309 // Signal to the named pipe instances that they should terminate. 368 // Signal to the named pipe instances that they should terminate.
310 for (int i = 0; i < arraysize(thread_handles); ++i) { 369 for (int i = 0; i < arraysize(thread_handles); ++i) {
311 ClientToServerMessage message; 370 ClientToServerMessage message;
312 memset(&message, 0, sizeof(message)); 371 memset(&message, 0, sizeof(message));
313 message.type = ClientToServerMessage::kShutdown; 372 message.type = ClientToServerMessage::kShutdown;
314 message.shutdown.token = shutdown_token; 373 message.shutdown.token = shutdown_token;
315 ServerToClientMessage response; 374 ServerToClientMessage response;
316 SendToCrashHandlerServer(pipe_name_16, 375 SendToCrashHandlerServer(pipe_name_,
317 reinterpret_cast<ClientToServerMessage&>(message), 376 reinterpret_cast<ClientToServerMessage&>(message),
318 &response); 377 &response);
319 } 378 }
320 379
321 for (auto& handle : thread_handles) 380 for (auto& handle : thread_handles)
322 WaitForSingleObject(handle.get(), INFINITE); 381 WaitForSingleObject(handle.get(), INFINITE);
323 382
324 // Deleting ClientData does a blocking wait until the threadpool executions 383 // Deleting ClientData does a blocking wait until the threadpool executions
325 // have terminated when unregistering them. 384 // have terminated when unregistering them.
326 { 385 {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) { 560 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) {
502 // This function is executed on the thread pool. 561 // This function is executed on the thread pool.
503 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); 562 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
504 base::AutoLock lock(*client->lock()); 563 base::AutoLock lock(*client->lock());
505 564
506 // Post back to the main thread to have it delete this client record. 565 // Post back to the main thread to have it delete this client record.
507 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr); 566 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr);
508 } 567 }
509 568
510 } // namespace crashpad 569 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/win/exception_handler_server.h ('k') | util/win/exception_handler_server_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698