/thirdparty/breakpad/client/windows/crash_generation/crash_generation_server.cc

http://github.com/tomahawk-player/tomahawk · C++ · 900 lines · 580 code · 152 blank · 168 comment · 112 complexity · a94fd8e9902472068b4245ee61b7b591 MD5 · raw file

  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. #include "client/windows/crash_generation/crash_generation_server.h"
  30. #include <windows.h>
  31. #include <cassert>
  32. #include <list>
  33. #include "client/windows/common/auto_critical_section.h"
  34. #include "processor/scoped_ptr.h"
  35. #include "client/windows/crash_generation/client_info.h"
  36. namespace google_breakpad {
  37. // Output buffer size.
  38. static const size_t kOutBufferSize = 64;
  39. // Input buffer size.
  40. static const size_t kInBufferSize = 64;
  41. // Access flags for the client on the dump request event.
  42. static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;
  43. // Access flags for the client on the dump generated event.
  44. static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
  45. SYNCHRONIZE;
  46. // Access flags for the client on the mutex.
  47. static const DWORD kMutexAccess = SYNCHRONIZE;
  48. // Attribute flags for the pipe.
  49. static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
  50. PIPE_ACCESS_DUPLEX |
  51. FILE_FLAG_OVERLAPPED;
  52. // Mode for the pipe.
  53. static const DWORD kPipeMode = PIPE_TYPE_MESSAGE |
  54. PIPE_READMODE_MESSAGE |
  55. PIPE_WAIT;
  56. // For pipe I/O, execute the callback in the wait thread itself,
  57. // since the callback does very little work. The callback executes
  58. // the code for one of the states of the server state machine and
  59. // the code for all of the states perform async I/O and hence
  60. // finish very quickly.
  61. static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD;
  62. // Dump request threads will, most likely, generate dumps. That may
  63. // take some time to finish, so specify WT_EXECUTELONGFUNCTION flag.
  64. static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
  65. WT_EXECUTELONGFUNCTION;
  66. // Maximum delay during server shutdown if some work items
  67. // are still executing.
  68. static const int kShutdownDelayMs = 10000;
  69. // Interval for each sleep during server shutdown.
  70. static const int kShutdownSleepIntervalMs = 5;
  71. static bool IsClientRequestValid(const ProtocolMessage& msg) {
  72. return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST ||
  73. (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
  74. msg.id != 0 &&
  75. msg.thread_id != NULL &&
  76. msg.exception_pointers != NULL &&
  77. msg.assert_info != NULL);
  78. }
  79. CrashGenerationServer::CrashGenerationServer(
  80. const std::wstring& pipe_name,
  81. SECURITY_ATTRIBUTES* pipe_sec_attrs,
  82. OnClientConnectedCallback connect_callback,
  83. void* connect_context,
  84. OnClientDumpRequestCallback dump_callback,
  85. void* dump_context,
  86. OnClientExitedCallback exit_callback,
  87. void* exit_context,
  88. OnClientUploadRequestCallback upload_request_callback,
  89. void* upload_context,
  90. bool generate_dumps,
  91. const std::wstring* dump_path)
  92. : pipe_name_(pipe_name),
  93. pipe_sec_attrs_(pipe_sec_attrs),
  94. pipe_(NULL),
  95. pipe_wait_handle_(NULL),
  96. server_alive_handle_(NULL),
  97. connect_callback_(connect_callback),
  98. connect_context_(connect_context),
  99. dump_callback_(dump_callback),
  100. dump_context_(dump_context),
  101. exit_callback_(exit_callback),
  102. exit_context_(exit_context),
  103. upload_request_callback_(upload_request_callback),
  104. upload_context_(upload_context),
  105. generate_dumps_(generate_dumps),
  106. dump_generator_(NULL),
  107. server_state_(IPC_SERVER_STATE_UNINITIALIZED),
  108. shutting_down_(false),
  109. overlapped_(),
  110. client_info_(NULL),
  111. cleanup_item_count_(0) {
  112. InitializeCriticalSection(&sync_);
  113. if (dump_path) {
  114. dump_generator_.reset(new MinidumpGenerator(*dump_path));
  115. }
  116. }
  117. CrashGenerationServer::~CrashGenerationServer() {
  118. // New scope to release the lock automatically.
  119. {
  120. AutoCriticalSection lock(&sync_);
  121. // Indicate to existing threads that server is shutting down.
  122. shutting_down_ = true;
  123. // Even if there are no current worker threads running, it is possible that
  124. // an I/O request is pending on the pipe right now but not yet done.
  125. // In fact, it's very likely this is the case unless we are in an ERROR
  126. // state. If we don't wait for the pending I/O to be done, then when the I/O
  127. // completes, it may write to invalid memory. AppVerifier will flag this
  128. // problem too. So we disconnect from the pipe and then wait for the server
  129. // to get into error state so that the pending I/O will fail and get
  130. // cleared.
  131. DisconnectNamedPipe(pipe_);
  132. int num_tries = 100;
  133. while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) {
  134. lock.Release();
  135. Sleep(10);
  136. lock.Acquire();
  137. }
  138. // Unregister wait on the pipe.
  139. if (pipe_wait_handle_) {
  140. // Wait for already executing callbacks to finish.
  141. UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
  142. }
  143. // Close the pipe to avoid further client connections.
  144. if (pipe_) {
  145. CloseHandle(pipe_);
  146. }
  147. // Request all ClientInfo objects to unregister all waits.
  148. std::list<ClientInfo*>::iterator iter;
  149. for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
  150. ClientInfo* client_info = *iter;
  151. client_info->UnregisterWaits();
  152. }
  153. }
  154. // Now that all waits have been unregistered, wait for some time
  155. // for all pending work items to finish.
  156. int total_wait = 0;
  157. while (cleanup_item_count_ > 0) {
  158. Sleep(kShutdownSleepIntervalMs);
  159. total_wait += kShutdownSleepIntervalMs;
  160. if (total_wait >= kShutdownDelayMs) {
  161. break;
  162. }
  163. }
  164. // New scope to hold the lock for the shortest time.
  165. {
  166. AutoCriticalSection lock(&sync_);
  167. // Clean up all the ClientInfo objects.
  168. std::list<ClientInfo*>::iterator iter;
  169. for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
  170. ClientInfo* client_info = *iter;
  171. delete client_info;
  172. }
  173. if (server_alive_handle_) {
  174. // Release the mutex before closing the handle so that clients requesting
  175. // dumps wait for a long time for the server to generate a dump.
  176. ReleaseMutex(server_alive_handle_);
  177. CloseHandle(server_alive_handle_);
  178. }
  179. if (overlapped_.hEvent) {
  180. CloseHandle(overlapped_.hEvent);
  181. }
  182. }
  183. DeleteCriticalSection(&sync_);
  184. }
  185. bool CrashGenerationServer::Start() {
  186. AutoCriticalSection lock(&sync_);
  187. if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) {
  188. return false;
  189. }
  190. server_state_ = IPC_SERVER_STATE_INITIAL;
  191. server_alive_handle_ = CreateMutex(NULL, TRUE, NULL);
  192. if (!server_alive_handle_) {
  193. return false;
  194. }
  195. // Event to signal the client connection and pipe reads and writes.
  196. overlapped_.hEvent = CreateEvent(NULL, // Security descriptor.
  197. TRUE, // Manual reset.
  198. FALSE, // Initially signaled.
  199. NULL); // Name.
  200. if (!overlapped_.hEvent) {
  201. return false;
  202. }
  203. // Register a callback with the thread pool for the client connection.
  204. if (!RegisterWaitForSingleObject(&pipe_wait_handle_,
  205. overlapped_.hEvent,
  206. OnPipeConnected,
  207. this,
  208. INFINITE,
  209. kPipeIOThreadFlags)) {
  210. return false;
  211. }
  212. pipe_ = CreateNamedPipe(pipe_name_.c_str(),
  213. kPipeAttr,
  214. kPipeMode,
  215. 1,
  216. kOutBufferSize,
  217. kInBufferSize,
  218. 0,
  219. pipe_sec_attrs_);
  220. if (pipe_ == INVALID_HANDLE_VALUE) {
  221. return false;
  222. }
  223. // Kick-start the state machine. This will initiate an asynchronous wait
  224. // for client connections.
  225. HandleInitialState();
  226. // If we are in error state, it's because we failed to start listening.
  227. return server_state_ != IPC_SERVER_STATE_ERROR;
  228. }
  229. // If the server thread serving clients ever gets into the
  230. // ERROR state, reset the event, close the pipe and remain
  231. // in the error state forever. Error state means something
  232. // that we didn't account for has happened, and it's dangerous
  233. // to do anything unknowingly.
  234. void CrashGenerationServer::HandleErrorState() {
  235. assert(server_state_ == IPC_SERVER_STATE_ERROR);
  236. // If the server is shutting down anyway, don't clean up
  237. // here since shut down process will clean up.
  238. if (shutting_down_) {
  239. return;
  240. }
  241. if (pipe_wait_handle_) {
  242. UnregisterWait(pipe_wait_handle_);
  243. pipe_wait_handle_ = NULL;
  244. }
  245. if (pipe_) {
  246. CloseHandle(pipe_);
  247. pipe_ = NULL;
  248. }
  249. if (overlapped_.hEvent) {
  250. CloseHandle(overlapped_.hEvent);
  251. overlapped_.hEvent = NULL;
  252. }
  253. }
  254. // When the server thread serving clients is in the INITIAL state,
  255. // try to connect to the pipe asynchronously. If the connection
  256. // finishes synchronously, directly go into the CONNECTED state;
  257. // otherwise go into the CONNECTING state. For any problems, go
  258. // into the ERROR state.
  259. void CrashGenerationServer::HandleInitialState() {
  260. assert(server_state_ == IPC_SERVER_STATE_INITIAL);
  261. if (!ResetEvent(overlapped_.hEvent)) {
  262. EnterErrorState();
  263. return;
  264. }
  265. bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE;
  266. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  267. // From MSDN, it is not clear that when ConnectNamedPipe is used
  268. // in an overlapped mode, will it ever return non-zero value, and
  269. // if so, in what cases.
  270. assert(!success);
  271. switch (error_code) {
  272. case ERROR_IO_PENDING:
  273. EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING);
  274. break;
  275. case ERROR_PIPE_CONNECTED:
  276. EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
  277. break;
  278. default:
  279. EnterErrorState();
  280. break;
  281. }
  282. }
  283. // When the server thread serving the clients is in the CONNECTING state,
  284. // try to get the result of the asynchronous connection request using
  285. // the OVERLAPPED object. If the result indicates the connection is done,
  286. // go into the CONNECTED state. If the result indicates I/O is still
  287. // INCOMPLETE, remain in the CONNECTING state. For any problems,
  288. // go into the DISCONNECTING state.
  289. void CrashGenerationServer::HandleConnectingState() {
  290. assert(server_state_ == IPC_SERVER_STATE_CONNECTING);
  291. DWORD bytes_count = 0;
  292. bool success = GetOverlappedResult(pipe_,
  293. &overlapped_,
  294. &bytes_count,
  295. FALSE) != FALSE;
  296. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  297. if (success) {
  298. EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
  299. } else if (error_code != ERROR_IO_INCOMPLETE) {
  300. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  301. } else {
  302. // remain in CONNECTING state
  303. }
  304. }
  305. // When the server thread serving the clients is in the CONNECTED state,
  306. // try to issue an asynchronous read from the pipe. If read completes
  307. // synchronously or if I/O is pending then go into the READING state.
  308. // For any problems, go into the DISCONNECTING state.
  309. void CrashGenerationServer::HandleConnectedState() {
  310. assert(server_state_ == IPC_SERVER_STATE_CONNECTED);
  311. DWORD bytes_count = 0;
  312. memset(&msg_, 0, sizeof(msg_));
  313. bool success = ReadFile(pipe_,
  314. &msg_,
  315. sizeof(msg_),
  316. &bytes_count,
  317. &overlapped_) != FALSE;
  318. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  319. // Note that the asynchronous read issued above can finish before the
  320. // code below executes. But, it is okay to change state after issuing
  321. // the asynchronous read. This is because even if the asynchronous read
  322. // is done, the callback for it would not be executed until the current
  323. // thread finishes its execution.
  324. if (success || error_code == ERROR_IO_PENDING) {
  325. EnterStateWhenSignaled(IPC_SERVER_STATE_READING);
  326. } else {
  327. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  328. }
  329. }
  330. // When the server thread serving the clients is in the READING state,
  331. // try to get the result of the async read. If async read is done,
  332. // go into the READ_DONE state. For any problems, go into the
  333. // DISCONNECTING state.
  334. void CrashGenerationServer::HandleReadingState() {
  335. assert(server_state_ == IPC_SERVER_STATE_READING);
  336. DWORD bytes_count = 0;
  337. bool success = GetOverlappedResult(pipe_,
  338. &overlapped_,
  339. &bytes_count,
  340. FALSE) != FALSE;
  341. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  342. if (success && bytes_count == sizeof(ProtocolMessage)) {
  343. EnterStateImmediately(IPC_SERVER_STATE_READ_DONE);
  344. } else {
  345. // We should never get an I/O incomplete since we should not execute this
  346. // unless the Read has finished and the overlapped event is signaled. If
  347. // we do get INCOMPLETE, we have a bug in our code.
  348. assert(error_code != ERROR_IO_INCOMPLETE);
  349. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  350. }
  351. }
  352. // When the server thread serving the client is in the READ_DONE state,
  353. // validate the client's request message, register the client by
  354. // creating appropriate objects and prepare the response. Then try to
  355. // write the response to the pipe asynchronously. If that succeeds,
  356. // go into the WRITING state. For any problems, go into the DISCONNECTING
  357. // state.
  358. void CrashGenerationServer::HandleReadDoneState() {
  359. assert(server_state_ == IPC_SERVER_STATE_READ_DONE);
  360. if (!IsClientRequestValid(msg_)) {
  361. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  362. return;
  363. }
  364. if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) {
  365. if (upload_request_callback_)
  366. upload_request_callback_(upload_context_, msg_.id);
  367. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  368. return;
  369. }
  370. scoped_ptr<ClientInfo> client_info(
  371. new ClientInfo(this,
  372. msg_.id,
  373. msg_.dump_type,
  374. msg_.thread_id,
  375. msg_.exception_pointers,
  376. msg_.assert_info,
  377. msg_.custom_client_info));
  378. if (!client_info->Initialize()) {
  379. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  380. return;
  381. }
  382. // Issues an asynchronous WriteFile call if successful.
  383. // Iff successful, assigns ownership of the client_info pointer to the server
  384. // instance, in which case we must be sure not to free it in this function.
  385. if (!RespondToClient(client_info.get())) {
  386. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  387. return;
  388. }
  389. client_info_ = client_info.release();
  390. // Note that the asynchronous write issued by RespondToClient function
  391. // can finish before the code below executes. But it is okay to change
  392. // state after issuing the asynchronous write. This is because even if
  393. // the asynchronous write is done, the callback for it would not be
  394. // executed until the current thread finishes its execution.
  395. EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING);
  396. }
  397. // When the server thread serving the clients is in the WRITING state,
  398. // try to get the result of the async write. If the async write is done,
  399. // go into the WRITE_DONE state. For any problems, go into the
  400. // DISONNECTING state.
  401. void CrashGenerationServer::HandleWritingState() {
  402. assert(server_state_ == IPC_SERVER_STATE_WRITING);
  403. DWORD bytes_count = 0;
  404. bool success = GetOverlappedResult(pipe_,
  405. &overlapped_,
  406. &bytes_count,
  407. FALSE) != FALSE;
  408. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  409. if (success) {
  410. EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE);
  411. return;
  412. }
  413. // We should never get an I/O incomplete since we should not execute this
  414. // unless the Write has finished and the overlapped event is signaled. If
  415. // we do get INCOMPLETE, we have a bug in our code.
  416. assert(error_code != ERROR_IO_INCOMPLETE);
  417. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  418. }
  419. // When the server thread serving the clients is in the WRITE_DONE state,
  420. // try to issue an async read on the pipe. If the read completes synchronously
  421. // or if I/O is still pending then go into the READING_ACK state. For any
  422. // issues, go into the DISCONNECTING state.
  423. void CrashGenerationServer::HandleWriteDoneState() {
  424. assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE);
  425. DWORD bytes_count = 0;
  426. bool success = ReadFile(pipe_,
  427. &msg_,
  428. sizeof(msg_),
  429. &bytes_count,
  430. &overlapped_) != FALSE;
  431. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  432. if (success) {
  433. EnterStateImmediately(IPC_SERVER_STATE_READING_ACK);
  434. } else if (error_code == ERROR_IO_PENDING) {
  435. EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK);
  436. } else {
  437. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  438. }
  439. }
  440. // When the server thread serving the clients is in the READING_ACK state,
  441. // try to get result of async read. Go into the DISCONNECTING state.
  442. void CrashGenerationServer::HandleReadingAckState() {
  443. assert(server_state_ == IPC_SERVER_STATE_READING_ACK);
  444. DWORD bytes_count = 0;
  445. bool success = GetOverlappedResult(pipe_,
  446. &overlapped_,
  447. &bytes_count,
  448. FALSE) != FALSE;
  449. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  450. if (success) {
  451. // The connection handshake with the client is now complete; perform
  452. // the callback.
  453. if (connect_callback_) {
  454. connect_callback_(connect_context_, client_info_);
  455. }
  456. } else {
  457. // We should never get an I/O incomplete since we should not execute this
  458. // unless the Read has finished and the overlapped event is signaled. If
  459. // we do get INCOMPLETE, we have a bug in our code.
  460. assert(error_code != ERROR_IO_INCOMPLETE);
  461. }
  462. EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  463. }
  464. // When the server thread serving the client is in the DISCONNECTING state,
  465. // disconnect from the pipe and reset the event. If anything fails, go into
  466. // the ERROR state. If it goes well, go into the INITIAL state and set the
  467. // event to start all over again.
  468. void CrashGenerationServer::HandleDisconnectingState() {
  469. assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING);
  470. // Done serving the client.
  471. client_info_ = NULL;
  472. overlapped_.Internal = NULL;
  473. overlapped_.InternalHigh = NULL;
  474. overlapped_.Offset = 0;
  475. overlapped_.OffsetHigh = 0;
  476. overlapped_.Pointer = NULL;
  477. if (!ResetEvent(overlapped_.hEvent)) {
  478. EnterErrorState();
  479. return;
  480. }
  481. if (!DisconnectNamedPipe(pipe_)) {
  482. EnterErrorState();
  483. return;
  484. }
  485. // If the server is shutting down do not connect to the
  486. // next client.
  487. if (shutting_down_) {
  488. return;
  489. }
  490. EnterStateImmediately(IPC_SERVER_STATE_INITIAL);
  491. }
  492. void CrashGenerationServer::EnterErrorState() {
  493. SetEvent(overlapped_.hEvent);
  494. server_state_ = IPC_SERVER_STATE_ERROR;
  495. }
  496. void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) {
  497. server_state_ = state;
  498. }
  499. void CrashGenerationServer::EnterStateImmediately(IPCServerState state) {
  500. server_state_ = state;
  501. if (!SetEvent(overlapped_.hEvent)) {
  502. server_state_ = IPC_SERVER_STATE_ERROR;
  503. }
  504. }
  505. bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
  506. ProtocolMessage* reply) const {
  507. reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
  508. reply->id = GetCurrentProcessId();
  509. if (CreateClientHandles(client_info, reply)) {
  510. return true;
  511. }
  512. if (reply->dump_request_handle) {
  513. CloseHandle(reply->dump_request_handle);
  514. }
  515. if (reply->dump_generated_handle) {
  516. CloseHandle(reply->dump_generated_handle);
  517. }
  518. if (reply->server_alive_handle) {
  519. CloseHandle(reply->server_alive_handle);
  520. }
  521. return false;
  522. }
  523. bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info,
  524. ProtocolMessage* reply) const {
  525. HANDLE current_process = GetCurrentProcess();
  526. if (!DuplicateHandle(current_process,
  527. client_info.dump_requested_handle(),
  528. client_info.process_handle(),
  529. &reply->dump_request_handle,
  530. kDumpRequestEventAccess,
  531. FALSE,
  532. 0)) {
  533. return false;
  534. }
  535. if (!DuplicateHandle(current_process,
  536. client_info.dump_generated_handle(),
  537. client_info.process_handle(),
  538. &reply->dump_generated_handle,
  539. kDumpGeneratedEventAccess,
  540. FALSE,
  541. 0)) {
  542. return false;
  543. }
  544. if (!DuplicateHandle(current_process,
  545. server_alive_handle_,
  546. client_info.process_handle(),
  547. &reply->server_alive_handle,
  548. kMutexAccess,
  549. FALSE,
  550. 0)) {
  551. return false;
  552. }
  553. return true;
  554. }
  555. bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) {
  556. ProtocolMessage reply;
  557. if (!PrepareReply(*client_info, &reply)) {
  558. return false;
  559. }
  560. DWORD bytes_count = 0;
  561. bool success = WriteFile(pipe_,
  562. &reply,
  563. sizeof(reply),
  564. &bytes_count,
  565. &overlapped_) != FALSE;
  566. DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
  567. if (!success && error_code != ERROR_IO_PENDING) {
  568. return false;
  569. }
  570. // Takes over ownership of client_info. We MUST return true if AddClient
  571. // succeeds.
  572. if (!AddClient(client_info)) {
  573. return false;
  574. }
  575. return true;
  576. }
  577. // The server thread servicing the clients runs this method. The method
  578. // implements the state machine described in ReadMe.txt along with the
  579. // helper methods HandleXXXState.
  580. void CrashGenerationServer::HandleConnectionRequest() {
  581. AutoCriticalSection lock(&sync_);
  582. // If we are shutting doen then get into ERROR state, reset the event so more
  583. // workers don't run and return immediately.
  584. if (shutting_down_) {
  585. server_state_ = IPC_SERVER_STATE_ERROR;
  586. ResetEvent(overlapped_.hEvent);
  587. return;
  588. }
  589. switch (server_state_) {
  590. case IPC_SERVER_STATE_ERROR:
  591. HandleErrorState();
  592. break;
  593. case IPC_SERVER_STATE_INITIAL:
  594. HandleInitialState();
  595. break;
  596. case IPC_SERVER_STATE_CONNECTING:
  597. HandleConnectingState();
  598. break;
  599. case IPC_SERVER_STATE_CONNECTED:
  600. HandleConnectedState();
  601. break;
  602. case IPC_SERVER_STATE_READING:
  603. HandleReadingState();
  604. break;
  605. case IPC_SERVER_STATE_READ_DONE:
  606. HandleReadDoneState();
  607. break;
  608. case IPC_SERVER_STATE_WRITING:
  609. HandleWritingState();
  610. break;
  611. case IPC_SERVER_STATE_WRITE_DONE:
  612. HandleWriteDoneState();
  613. break;
  614. case IPC_SERVER_STATE_READING_ACK:
  615. HandleReadingAckState();
  616. break;
  617. case IPC_SERVER_STATE_DISCONNECTING:
  618. HandleDisconnectingState();
  619. break;
  620. default:
  621. assert(false);
  622. // This indicates that we added one more state without
  623. // adding handling code.
  624. server_state_ = IPC_SERVER_STATE_ERROR;
  625. break;
  626. }
  627. }
  628. bool CrashGenerationServer::AddClient(ClientInfo* client_info) {
  629. HANDLE request_wait_handle = NULL;
  630. if (!RegisterWaitForSingleObject(&request_wait_handle,
  631. client_info->dump_requested_handle(),
  632. OnDumpRequest,
  633. client_info,
  634. INFINITE,
  635. kDumpRequestThreadFlags)) {
  636. return false;
  637. }
  638. client_info->set_dump_request_wait_handle(request_wait_handle);
  639. // OnClientEnd will be called when the client process terminates.
  640. HANDLE process_wait_handle = NULL;
  641. if (!RegisterWaitForSingleObject(&process_wait_handle,
  642. client_info->process_handle(),
  643. OnClientEnd,
  644. client_info,
  645. INFINITE,
  646. WT_EXECUTEONLYONCE)) {
  647. return false;
  648. }
  649. client_info->set_process_exit_wait_handle(process_wait_handle);
  650. // New scope to hold the lock for the shortest time.
  651. {
  652. AutoCriticalSection lock(&sync_);
  653. clients_.push_back(client_info);
  654. }
  655. return true;
  656. }
  657. // static
  658. void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) {
  659. assert(context);
  660. CrashGenerationServer* obj =
  661. reinterpret_cast<CrashGenerationServer*>(context);
  662. obj->HandleConnectionRequest();
  663. }
  664. // static
  665. void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) {
  666. assert(context);
  667. ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
  668. client_info->PopulateCustomInfo();
  669. CrashGenerationServer* crash_server = client_info->crash_server();
  670. assert(crash_server);
  671. crash_server->HandleDumpRequest(*client_info);
  672. ResetEvent(client_info->dump_requested_handle());
  673. }
  674. // static
  675. void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) {
  676. assert(context);
  677. ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
  678. CrashGenerationServer* crash_server = client_info->crash_server();
  679. assert(crash_server);
  680. client_info->UnregisterWaits();
  681. InterlockedIncrement(&crash_server->cleanup_item_count_);
  682. if (!QueueUserWorkItem(CleanupClient, context, WT_EXECUTEDEFAULT)) {
  683. InterlockedDecrement(&crash_server->cleanup_item_count_);
  684. }
  685. }
  686. // static
  687. DWORD WINAPI CrashGenerationServer::CleanupClient(void* context) {
  688. assert(context);
  689. ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
  690. CrashGenerationServer* crash_server = client_info->crash_server();
  691. assert(crash_server);
  692. if (crash_server->exit_callback_) {
  693. crash_server->exit_callback_(crash_server->exit_context_, client_info);
  694. }
  695. crash_server->DoCleanup(client_info);
  696. InterlockedDecrement(&crash_server->cleanup_item_count_);
  697. return 0;
  698. }
  699. void CrashGenerationServer::DoCleanup(ClientInfo* client_info) {
  700. assert(client_info);
  701. // Start a new scope to release lock automatically.
  702. {
  703. AutoCriticalSection lock(&sync_);
  704. clients_.remove(client_info);
  705. }
  706. delete client_info;
  707. }
  708. void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) {
  709. // Generate the dump only if it's explicitly requested by the
  710. // server application; otherwise the server might want to generate
  711. // dump in the callback.
  712. std::wstring dump_path;
  713. if (generate_dumps_) {
  714. if (!GenerateDump(client_info, &dump_path)) {
  715. return;
  716. }
  717. }
  718. if (dump_callback_) {
  719. std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path;
  720. dump_callback_(dump_context_, &client_info, ptr_dump_path);
  721. }
  722. SetEvent(client_info.dump_generated_handle());
  723. }
  724. bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
  725. std::wstring* dump_path) {
  726. assert(client.pid() != 0);
  727. assert(client.process_handle());
  728. // We have to get the address of EXCEPTION_INFORMATION from
  729. // the client process address space.
  730. EXCEPTION_POINTERS* client_ex_info = NULL;
  731. if (!client.GetClientExceptionInfo(&client_ex_info)) {
  732. return false;
  733. }
  734. DWORD client_thread_id = 0;
  735. if (!client.GetClientThreadId(&client_thread_id)) {
  736. return false;
  737. }
  738. return dump_generator_->WriteMinidump(client.process_handle(),
  739. client.pid(),
  740. client_thread_id,
  741. GetCurrentThreadId(),
  742. client_ex_info,
  743. client.assert_info(),
  744. client.dump_type(),
  745. true,
  746. dump_path);
  747. }
  748. } // namespace google_breakpad