1 // Copyright (c) 2008, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 #include "client/windows/crash_generation/crash_generation_server.h" 31 #include <windows.h> 32 #include <cassert> 33 #include <list> 34 #include "client/windows/common/auto_critical_section.h" 35 #include "common/scoped_ptr.h" 36 37 #include "client/windows/crash_generation/client_info.h" 38 39 namespace google_breakpad { 40 41 // Output buffer size. 42 static const size_t kOutBufferSize = 64; 43 44 // Input buffer size. 45 static const size_t kInBufferSize = 64; 46 47 // Access flags for the client on the dump request event. 48 static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE; 49 50 // Access flags for the client on the dump generated event. 51 static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE | 52 SYNCHRONIZE; 53 54 // Access flags for the client on the mutex. 55 static const DWORD kMutexAccess = SYNCHRONIZE; 56 57 // Attribute flags for the pipe. 58 static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE | 59 PIPE_ACCESS_DUPLEX | 60 FILE_FLAG_OVERLAPPED; 61 62 // Mode for the pipe. 63 static const DWORD kPipeMode = PIPE_TYPE_MESSAGE | 64 PIPE_READMODE_MESSAGE | 65 PIPE_WAIT; 66 67 // For pipe I/O, execute the callback in the wait thread itself, 68 // since the callback does very little work. The callback executes 69 // the code for one of the states of the server state machine and 70 // the code for all of the states perform async I/O and hence 71 // finish very quickly. 72 static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD; 73 74 // Dump request threads will, most likely, generate dumps. That may 75 // take some time to finish, so specify WT_EXECUTELONGFUNCTION flag. 76 static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD | 77 WT_EXECUTELONGFUNCTION; 78 79 static bool IsClientRequestValid(const ProtocolMessage& msg) { 80 return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST || 81 (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST && 82 msg.id != 0 && 83 msg.thread_id != NULL && 84 msg.exception_pointers != NULL && 85 msg.assert_info != NULL); 86 } 87 88 #ifdef _DEBUG 89 static bool CheckForIOIncomplete(bool success) { 90 // We should never get an I/O incomplete since we should not execute this 91 // unless the operation has finished and the overlapped event is signaled. If 92 // we do get INCOMPLETE, we have a bug in our code. 93 return success ? false : (GetLastError() == ERROR_IO_INCOMPLETE); 94 } 95 #endif 96 97 CrashGenerationServer::CrashGenerationServer( 98 const std::wstring& pipe_name, 99 SECURITY_ATTRIBUTES* pipe_sec_attrs, 100 OnClientConnectedCallback connect_callback, 101 void* connect_context, 102 OnClientDumpRequestCallback dump_callback, 103 void* dump_context, 104 OnClientExitedCallback exit_callback, 105 void* exit_context, 106 OnClientUploadRequestCallback upload_request_callback, 107 void* upload_context, 108 bool generate_dumps, 109 const std::wstring* dump_path) 110 : pipe_name_(pipe_name), 111 pipe_sec_attrs_(pipe_sec_attrs), 112 pipe_(NULL), 113 pipe_wait_handle_(NULL), 114 server_alive_handle_(NULL), 115 connect_callback_(connect_callback), 116 connect_context_(connect_context), 117 dump_callback_(dump_callback), 118 dump_context_(dump_context), 119 exit_callback_(exit_callback), 120 exit_context_(exit_context), 121 upload_request_callback_(upload_request_callback), 122 upload_context_(upload_context), 123 generate_dumps_(generate_dumps), 124 dump_path_(dump_path ? *dump_path : L""), 125 server_state_(IPC_SERVER_STATE_UNINITIALIZED), 126 shutting_down_(false), 127 overlapped_(), 128 client_info_(NULL), 129 pre_fetch_custom_info_(true) { 130 InitializeCriticalSection(&sync_); 131 } 132 133 // This should never be called from the OnPipeConnected callback. 134 // Otherwise the UnregisterWaitEx call below will cause a deadlock. 135 CrashGenerationServer::~CrashGenerationServer() { 136 // New scope to release the lock automatically. 137 { 138 // Make sure no clients are added or removed beyond this point. 139 // Before adding or removing any clients, the critical section 140 // must be entered and the shutting_down_ flag checked. The 141 // critical section is then exited only after the clients_ list 142 // modifications are done and the list is in a consistent state. 143 AutoCriticalSection lock(&sync_); 144 145 // Indicate to existing threads that server is shutting down. 146 shutting_down_ = true; 147 } 148 // No one will modify the clients_ list beyond this point - 149 // not even from another thread. 150 151 // Even if there are no current worker threads running, it is possible that 152 // an I/O request is pending on the pipe right now but not yet done. 153 // In fact, it's very likely this is the case unless we are in an ERROR 154 // state. If we don't wait for the pending I/O to be done, then when the I/O 155 // completes, it may write to invalid memory. AppVerifier will flag this 156 // problem too. So we disconnect from the pipe and then wait for the server 157 // to get into error state so that the pending I/O will fail and get 158 // cleared. 159 DisconnectNamedPipe(pipe_); 160 int num_tries = 100; 161 while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) { 162 Sleep(10); 163 } 164 165 // Unregister wait on the pipe. 166 if (pipe_wait_handle_) { 167 // Wait for already executing callbacks to finish. 168 UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE); 169 } 170 171 // Close the pipe to avoid further client connections. 172 if (pipe_) { 173 CloseHandle(pipe_); 174 } 175 176 // Request all ClientInfo objects to unregister all waits. 177 // No need to enter the critical section because no one is allowed to modify 178 // the clients_ list once the shutting_down_ flag is set. 179 std::list<ClientInfo*>::iterator iter; 180 for (iter = clients_.begin(); iter != clients_.end(); ++iter) { 181 ClientInfo* client_info = *iter; 182 // Unregister waits. Wait for already executing callbacks to finish. 183 // Unregister the client process exit wait first and only then unregister 184 // the dump request wait. The reason is that the OnClientExit callback 185 // also unregisters the dump request wait and such a race (doing the same 186 // unregistration from two threads) is undesirable. 187 client_info->UnregisterProcessExitWait(true); 188 client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); 189 190 // Destroying the ClientInfo here is safe because all wait operations for 191 // this ClientInfo were unregistered and no pending or running callbacks 192 // for this ClientInfo can possible exist (block_until_no_pending option 193 // was used). 194 delete client_info; 195 } 196 197 if (server_alive_handle_) { 198 // Release the mutex before closing the handle so that clients requesting 199 // dumps wait for a long time for the server to generate a dump. 200 ReleaseMutex(server_alive_handle_); 201 CloseHandle(server_alive_handle_); 202 } 203 204 if (overlapped_.hEvent) { 205 CloseHandle(overlapped_.hEvent); 206 } 207 208 DeleteCriticalSection(&sync_); 209 } 210 211 bool CrashGenerationServer::Start() { 212 if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) { 213 return false; 214 } 215 216 server_state_ = IPC_SERVER_STATE_INITIAL; 217 218 server_alive_handle_ = CreateMutex(NULL, TRUE, NULL); 219 if (!server_alive_handle_) { 220 return false; 221 } 222 223 // Event to signal the client connection and pipe reads and writes. 224 overlapped_.hEvent = CreateEvent(NULL, // Security descriptor. 225 TRUE, // Manual reset. 226 FALSE, // Initially nonsignaled. 227 NULL); // Name. 228 if (!overlapped_.hEvent) { 229 return false; 230 } 231 232 // Register a callback with the thread pool for the client connection. 233 if (!RegisterWaitForSingleObject(&pipe_wait_handle_, 234 overlapped_.hEvent, 235 OnPipeConnected, 236 this, 237 INFINITE, 238 kPipeIOThreadFlags)) { 239 return false; 240 } 241 242 pipe_ = CreateNamedPipe(pipe_name_.c_str(), 243 kPipeAttr, 244 kPipeMode, 245 1, 246 kOutBufferSize, 247 kInBufferSize, 248 0, 249 pipe_sec_attrs_); 250 if (pipe_ == INVALID_HANDLE_VALUE) { 251 return false; 252 } 253 254 // Kick-start the state machine. This will initiate an asynchronous wait 255 // for client connections. 256 if (!SetEvent(overlapped_.hEvent)) { 257 server_state_ = IPC_SERVER_STATE_ERROR; 258 return false; 259 } 260 261 // If we are in error state, it's because we failed to start listening. 262 return true; 263 } 264 265 // If the server thread serving clients ever gets into the 266 // ERROR state, reset the event, close the pipe and remain 267 // in the error state forever. Error state means something 268 // that we didn't account for has happened, and it's dangerous 269 // to do anything unknowingly. 270 void CrashGenerationServer::HandleErrorState() { 271 assert(server_state_ == IPC_SERVER_STATE_ERROR); 272 273 // If the server is shutting down anyway, don't clean up 274 // here since shut down process will clean up. 275 if (shutting_down_) { 276 return; 277 } 278 279 if (pipe_wait_handle_) { 280 UnregisterWait(pipe_wait_handle_); 281 pipe_wait_handle_ = NULL; 282 } 283 284 if (pipe_) { 285 CloseHandle(pipe_); 286 pipe_ = NULL; 287 } 288 289 if (overlapped_.hEvent) { 290 CloseHandle(overlapped_.hEvent); 291 overlapped_.hEvent = NULL; 292 } 293 } 294 295 // When the server thread serving clients is in the INITIAL state, 296 // try to connect to the pipe asynchronously. If the connection 297 // finishes synchronously, directly go into the CONNECTED state; 298 // otherwise go into the CONNECTING state. For any problems, go 299 // into the ERROR state. 300 void CrashGenerationServer::HandleInitialState() { 301 assert(server_state_ == IPC_SERVER_STATE_INITIAL); 302 303 if (!ResetEvent(overlapped_.hEvent)) { 304 EnterErrorState(); 305 return; 306 } 307 308 bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE; 309 DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); 310 311 // From MSDN, it is not clear that when ConnectNamedPipe is used 312 // in an overlapped mode, will it ever return non-zero value, and 313 // if so, in what cases. 314 assert(!success); 315 316 switch (error_code) { 317 case ERROR_IO_PENDING: 318 EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING); 319 break; 320 321 case ERROR_PIPE_CONNECTED: 322 EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); 323 break; 324 325 default: 326 EnterErrorState(); 327 break; 328 } 329 } 330 331 // When the server thread serving the clients is in the CONNECTING state, 332 // try to get the result of the asynchronous connection request using 333 // the OVERLAPPED object. If the result indicates the connection is done, 334 // go into the CONNECTED state. If the result indicates I/O is still 335 // INCOMPLETE, remain in the CONNECTING state. For any problems, 336 // go into the DISCONNECTING state. 337 void CrashGenerationServer::HandleConnectingState() { 338 assert(server_state_ == IPC_SERVER_STATE_CONNECTING); 339 340 DWORD bytes_count = 0; 341 bool success = GetOverlappedResult(pipe_, 342 &overlapped_, 343 &bytes_count, 344 FALSE) != FALSE; 345 DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); 346 347 if (success) { 348 EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); 349 } else if (error_code != ERROR_IO_INCOMPLETE) { 350 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 351 } else { 352 // remain in CONNECTING state 353 } 354 } 355 356 // When the server thread serving the clients is in the CONNECTED state, 357 // try to issue an asynchronous read from the pipe. If read completes 358 // synchronously or if I/O is pending then go into the READING state. 359 // For any problems, go into the DISCONNECTING state. 360 void CrashGenerationServer::HandleConnectedState() { 361 assert(server_state_ == IPC_SERVER_STATE_CONNECTED); 362 363 DWORD bytes_count = 0; 364 memset(&msg_, 0, sizeof(msg_)); 365 bool success = ReadFile(pipe_, 366 &msg_, 367 sizeof(msg_), 368 &bytes_count, 369 &overlapped_) != FALSE; 370 DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); 371 372 // Note that the asynchronous read issued above can finish before the 373 // code below executes. But, it is okay to change state after issuing 374 // the asynchronous read. This is because even if the asynchronous read 375 // is done, the callback for it would not be executed until the current 376 // thread finishes its execution. 377 if (success || error_code == ERROR_IO_PENDING) { 378 EnterStateWhenSignaled(IPC_SERVER_STATE_READING); 379 } else { 380 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 381 } 382 } 383 384 // When the server thread serving the clients is in the READING state, 385 // try to get the result of the async read. If async read is done, 386 // go into the READ_DONE state. For any problems, go into the 387 // DISCONNECTING state. 388 void CrashGenerationServer::HandleReadingState() { 389 assert(server_state_ == IPC_SERVER_STATE_READING); 390 391 DWORD bytes_count = 0; 392 bool success = GetOverlappedResult(pipe_, 393 &overlapped_, 394 &bytes_count, 395 FALSE) != FALSE; 396 if (success && bytes_count == sizeof(ProtocolMessage)) { 397 EnterStateImmediately(IPC_SERVER_STATE_READ_DONE); 398 return; 399 } 400 401 assert(!CheckForIOIncomplete(success)); 402 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 403 } 404 405 // When the server thread serving the client is in the READ_DONE state, 406 // validate the client's request message, register the client by 407 // creating appropriate objects and prepare the response. Then try to 408 // write the response to the pipe asynchronously. If that succeeds, 409 // go into the WRITING state. For any problems, go into the DISCONNECTING 410 // state. 411 void CrashGenerationServer::HandleReadDoneState() { 412 assert(server_state_ == IPC_SERVER_STATE_READ_DONE); 413 414 if (!IsClientRequestValid(msg_)) { 415 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 416 return; 417 } 418 419 if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) { 420 if (upload_request_callback_) 421 upload_request_callback_(upload_context_, msg_.id); 422 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 423 return; 424 } 425 426 scoped_ptr<ClientInfo> client_info( 427 new ClientInfo(this, 428 msg_.id, 429 msg_.dump_type, 430 msg_.thread_id, 431 msg_.exception_pointers, 432 msg_.assert_info, 433 msg_.custom_client_info)); 434 435 if (!client_info->Initialize()) { 436 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 437 return; 438 } 439 440 // Issues an asynchronous WriteFile call if successful. 441 // Iff successful, assigns ownership of the client_info pointer to the server 442 // instance, in which case we must be sure not to free it in this function. 443 if (!RespondToClient(client_info.get())) { 444 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 445 return; 446 } 447 448 // This is only valid as long as it can be found in the clients_ list 449 client_info_ = client_info.release(); 450 451 // Note that the asynchronous write issued by RespondToClient function 452 // can finish before the code below executes. But it is okay to change 453 // state after issuing the asynchronous write. This is because even if 454 // the asynchronous write is done, the callback for it would not be 455 // executed until the current thread finishes its execution. 456 EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING); 457 } 458 459 // When the server thread serving the clients is in the WRITING state, 460 // try to get the result of the async write. If the async write is done, 461 // go into the WRITE_DONE state. For any problems, go into the 462 // DISONNECTING state. 463 void CrashGenerationServer::HandleWritingState() { 464 assert(server_state_ == IPC_SERVER_STATE_WRITING); 465 466 DWORD bytes_count = 0; 467 bool success = GetOverlappedResult(pipe_, 468 &overlapped_, 469 &bytes_count, 470 FALSE) != FALSE; 471 if (success) { 472 EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE); 473 return; 474 } 475 476 assert(!CheckForIOIncomplete(success)); 477 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 478 } 479 480 // When the server thread serving the clients is in the WRITE_DONE state, 481 // try to issue an async read on the pipe. If the read completes synchronously 482 // or if I/O is still pending then go into the READING_ACK state. For any 483 // issues, go into the DISCONNECTING state. 484 void CrashGenerationServer::HandleWriteDoneState() { 485 assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE); 486 487 DWORD bytes_count = 0; 488 bool success = ReadFile(pipe_, 489 &msg_, 490 sizeof(msg_), 491 &bytes_count, 492 &overlapped_) != FALSE; 493 DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); 494 495 if (success) { 496 EnterStateImmediately(IPC_SERVER_STATE_READING_ACK); 497 } else if (error_code == ERROR_IO_PENDING) { 498 EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK); 499 } else { 500 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 501 } 502 } 503 504 // When the server thread serving the clients is in the READING_ACK state, 505 // try to get result of async read. Go into the DISCONNECTING state. 506 void CrashGenerationServer::HandleReadingAckState() { 507 assert(server_state_ == IPC_SERVER_STATE_READING_ACK); 508 509 DWORD bytes_count = 0; 510 bool success = GetOverlappedResult(pipe_, 511 &overlapped_, 512 &bytes_count, 513 FALSE) != FALSE; 514 if (success) { 515 // The connection handshake with the client is now complete; perform 516 // the callback. 517 if (connect_callback_) { 518 // Note that there is only a single copy of the ClientInfo of the 519 // currently connected client. However it is being referenced from 520 // two different places: 521 // - the client_info_ member 522 // - the clients_ list 523 // The lifetime of this ClientInfo depends on the lifetime of the 524 // client process - basically it can go away at any time. 525 // However, as long as it is referenced by the clients_ list it 526 // is guaranteed to be valid. Enter the critical section and check 527 // to see whether the client_info_ can be found in the list. 528 // If found, execute the callback and only then leave the critical 529 // section. 530 AutoCriticalSection lock(&sync_); 531 532 bool client_is_still_alive = false; 533 std::list<ClientInfo*>::iterator iter; 534 for (iter = clients_.begin(); iter != clients_.end(); ++iter) { 535 if (client_info_ == *iter) { 536 client_is_still_alive = true; 537 break; 538 } 539 } 540 541 if (client_is_still_alive) { 542 connect_callback_(connect_context_, client_info_); 543 } 544 } 545 } else { 546 assert(!CheckForIOIncomplete(success)); 547 } 548 549 EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); 550 } 551 552 // When the server thread serving the client is in the DISCONNECTING state, 553 // disconnect from the pipe and reset the event. If anything fails, go into 554 // the ERROR state. If it goes well, go into the INITIAL state and set the 555 // event to start all over again. 556 void CrashGenerationServer::HandleDisconnectingState() { 557 assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING); 558 559 // Done serving the client. 560 client_info_ = NULL; 561 562 overlapped_.Internal = NULL; 563 overlapped_.InternalHigh = NULL; 564 overlapped_.Offset = 0; 565 overlapped_.OffsetHigh = 0; 566 overlapped_.Pointer = NULL; 567 568 if (!ResetEvent(overlapped_.hEvent)) { 569 EnterErrorState(); 570 return; 571 } 572 573 if (!DisconnectNamedPipe(pipe_)) { 574 EnterErrorState(); 575 return; 576 } 577 578 // If the server is shutting down do not connect to the 579 // next client. 580 if (shutting_down_) { 581 return; 582 } 583 584 EnterStateImmediately(IPC_SERVER_STATE_INITIAL); 585 } 586 587 void CrashGenerationServer::EnterErrorState() { 588 SetEvent(overlapped_.hEvent); 589 server_state_ = IPC_SERVER_STATE_ERROR; 590 } 591 592 void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) { 593 server_state_ = state; 594 } 595 596 void CrashGenerationServer::EnterStateImmediately(IPCServerState state) { 597 server_state_ = state; 598 599 if (!SetEvent(overlapped_.hEvent)) { 600 server_state_ = IPC_SERVER_STATE_ERROR; 601 } 602 } 603 604 bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info, 605 ProtocolMessage* reply) const { 606 reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE; 607 reply->id = GetCurrentProcessId(); 608 609 if (CreateClientHandles(client_info, reply)) { 610 return true; 611 } 612 613 // Closing of remote handles (belonging to a different process) can 614 // only be done through DuplicateHandle. 615 if (reply->dump_request_handle) { 616 DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle 617 reply->dump_request_handle, // hSourceHandle 618 NULL, // hTargetProcessHandle 619 0, // lpTargetHandle 620 0, // dwDesiredAccess 621 FALSE, // bInheritHandle 622 DUPLICATE_CLOSE_SOURCE); // dwOptions 623 reply->dump_request_handle = NULL; 624 } 625 626 if (reply->dump_generated_handle) { 627 DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle 628 reply->dump_generated_handle, // hSourceHandle 629 NULL, // hTargetProcessHandle 630 0, // lpTargetHandle 631 0, // dwDesiredAccess 632 FALSE, // bInheritHandle 633 DUPLICATE_CLOSE_SOURCE); // dwOptions 634 reply->dump_generated_handle = NULL; 635 } 636 637 if (reply->server_alive_handle) { 638 DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle 639 reply->server_alive_handle, // hSourceHandle 640 NULL, // hTargetProcessHandle 641 0, // lpTargetHandle 642 0, // dwDesiredAccess 643 FALSE, // bInheritHandle 644 DUPLICATE_CLOSE_SOURCE); // dwOptions 645 reply->server_alive_handle = NULL; 646 } 647 648 return false; 649 } 650 651 bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info, 652 ProtocolMessage* reply) const { 653 HANDLE current_process = GetCurrentProcess(); 654 if (!DuplicateHandle(current_process, 655 client_info.dump_requested_handle(), 656 client_info.process_handle(), 657 &reply->dump_request_handle, 658 kDumpRequestEventAccess, 659 FALSE, 660 0)) { 661 return false; 662 } 663 664 if (!DuplicateHandle(current_process, 665 client_info.dump_generated_handle(), 666 client_info.process_handle(), 667 &reply->dump_generated_handle, 668 kDumpGeneratedEventAccess, 669 FALSE, 670 0)) { 671 return false; 672 } 673 674 if (!DuplicateHandle(current_process, 675 server_alive_handle_, 676 client_info.process_handle(), 677 &reply->server_alive_handle, 678 kMutexAccess, 679 FALSE, 680 0)) { 681 return false; 682 } 683 684 return true; 685 } 686 687 bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) { 688 ProtocolMessage reply; 689 if (!PrepareReply(*client_info, &reply)) { 690 return false; 691 } 692 693 DWORD bytes_count = 0; 694 bool success = WriteFile(pipe_, 695 &reply, 696 sizeof(reply), 697 &bytes_count, 698 &overlapped_) != FALSE; 699 DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); 700 701 if (!success && error_code != ERROR_IO_PENDING) { 702 return false; 703 } 704 705 // Takes over ownership of client_info. We MUST return true if AddClient 706 // succeeds. 707 return AddClient(client_info); 708 } 709 710 // The server thread servicing the clients runs this method. The method 711 // implements the state machine described in ReadMe.txt along with the 712 // helper methods HandleXXXState. 713 void CrashGenerationServer::HandleConnectionRequest() { 714 // If the server is shutting down, get into ERROR state, reset the event so 715 // more workers don't run and return immediately. 716 if (shutting_down_) { 717 server_state_ = IPC_SERVER_STATE_ERROR; 718 ResetEvent(overlapped_.hEvent); 719 return; 720 } 721 722 switch (server_state_) { 723 case IPC_SERVER_STATE_ERROR: 724 HandleErrorState(); 725 break; 726 727 case IPC_SERVER_STATE_INITIAL: 728 HandleInitialState(); 729 break; 730 731 case IPC_SERVER_STATE_CONNECTING: 732 HandleConnectingState(); 733 break; 734 735 case IPC_SERVER_STATE_CONNECTED: 736 HandleConnectedState(); 737 break; 738 739 case IPC_SERVER_STATE_READING: 740 HandleReadingState(); 741 break; 742 743 case IPC_SERVER_STATE_READ_DONE: 744 HandleReadDoneState(); 745 break; 746 747 case IPC_SERVER_STATE_WRITING: 748 HandleWritingState(); 749 break; 750 751 case IPC_SERVER_STATE_WRITE_DONE: 752 HandleWriteDoneState(); 753 break; 754 755 case IPC_SERVER_STATE_READING_ACK: 756 HandleReadingAckState(); 757 break; 758 759 case IPC_SERVER_STATE_DISCONNECTING: 760 HandleDisconnectingState(); 761 break; 762 763 default: 764 assert(false); 765 // This indicates that we added one more state without 766 // adding handling code. 767 server_state_ = IPC_SERVER_STATE_ERROR; 768 break; 769 } 770 } 771 772 bool CrashGenerationServer::AddClient(ClientInfo* client_info) { 773 HANDLE request_wait_handle = NULL; 774 if (!RegisterWaitForSingleObject(&request_wait_handle, 775 client_info->dump_requested_handle(), 776 OnDumpRequest, 777 client_info, 778 INFINITE, 779 kDumpRequestThreadFlags)) { 780 return false; 781 } 782 783 client_info->set_dump_request_wait_handle(request_wait_handle); 784 785 // OnClientEnd will be called when the client process terminates. 786 HANDLE process_wait_handle = NULL; 787 if (!RegisterWaitForSingleObject(&process_wait_handle, 788 client_info->process_handle(), 789 OnClientEnd, 790 client_info, 791 INFINITE, 792 WT_EXECUTEONLYONCE)) { 793 return false; 794 } 795 796 client_info->set_process_exit_wait_handle(process_wait_handle); 797 798 // New scope to hold the lock for the shortest time. 799 { 800 AutoCriticalSection lock(&sync_); 801 if (shutting_down_) { 802 // If server is shutting down, don't add new clients 803 return false; 804 } 805 clients_.push_back(client_info); 806 } 807 808 return true; 809 } 810 811 // static 812 void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) { 813 assert(context); 814 815 CrashGenerationServer* obj = 816 reinterpret_cast<CrashGenerationServer*>(context); 817 obj->HandleConnectionRequest(); 818 } 819 820 // static 821 void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) { 822 assert(context); 823 ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); 824 825 CrashGenerationServer* crash_server = client_info->crash_server(); 826 assert(crash_server); 827 if (crash_server->pre_fetch_custom_info_) { 828 client_info->PopulateCustomInfo(); 829 } 830 crash_server->HandleDumpRequest(*client_info); 831 832 ResetEvent(client_info->dump_requested_handle()); 833 } 834 835 // static 836 void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) { 837 assert(context); 838 ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); 839 840 CrashGenerationServer* crash_server = client_info->crash_server(); 841 assert(crash_server); 842 843 crash_server->HandleClientProcessExit(client_info); 844 } 845 846 void CrashGenerationServer::HandleClientProcessExit(ClientInfo* client_info) { 847 assert(client_info); 848 849 // Must unregister the dump request wait operation and wait for any 850 // dump requests that might be pending to finish before proceeding 851 // with the client_info cleanup. 852 client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); 853 854 if (exit_callback_) { 855 exit_callback_(exit_context_, client_info); 856 } 857 858 // Start a new scope to release lock automatically. 859 { 860 AutoCriticalSection lock(&sync_); 861 if (shutting_down_) { 862 // The crash generation server is shutting down and as part of the 863 // shutdown process it will delete all clients from the clients_ list. 864 return; 865 } 866 clients_.remove(client_info); 867 } 868 869 // Explicitly unregister the process exit wait using the non-blocking method. 870 // Otherwise, the destructor will attempt to unregister it using the blocking 871 // method which will lead to a deadlock because it is being called from the 872 // callback of the same wait operation 873 client_info->UnregisterProcessExitWait(false); 874 875 delete client_info; 876 } 877 878 void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) { 879 bool execute_callback = true; 880 // Generate the dump only if it's explicitly requested by the 881 // server application; otherwise the server might want to generate 882 // dump in the callback. 883 std::wstring dump_path; 884 if (generate_dumps_) { 885 if (!GenerateDump(client_info, &dump_path)) { 886 // client proccess terminated or some other error 887 execute_callback = false; 888 } 889 } 890 891 if (dump_callback_ && execute_callback) { 892 std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path; 893 dump_callback_(dump_context_, &client_info, ptr_dump_path); 894 } 895 896 SetEvent(client_info.dump_generated_handle()); 897 } 898 899 bool CrashGenerationServer::GenerateDump(const ClientInfo& client, 900 std::wstring* dump_path) { 901 assert(client.pid() != 0); 902 assert(client.process_handle()); 903 904 // We have to get the address of EXCEPTION_INFORMATION from 905 // the client process address space. 906 EXCEPTION_POINTERS* client_ex_info = NULL; 907 if (!client.GetClientExceptionInfo(&client_ex_info)) { 908 return false; 909 } 910 911 DWORD client_thread_id = 0; 912 if (!client.GetClientThreadId(&client_thread_id)) { 913 return false; 914 } 915 916 MinidumpGenerator dump_generator(dump_path_, 917 client.process_handle(), 918 client.pid(), 919 client_thread_id, 920 GetCurrentThreadId(), 921 client_ex_info, 922 client.assert_info(), 923 client.dump_type(), 924 true); 925 if (!dump_generator.GenerateDumpFile(dump_path)) { 926 return false; 927 } 928 return dump_generator.WriteMinidump(); 929 } 930 931 } // namespace google_breakpad 932