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
39namespace google_breakpad {
40
41// Output buffer size.
42static const size_t kOutBufferSize = 64;
43
44// Input buffer size.
45static const size_t kInBufferSize = 64;
46
47// Access flags for the client on the dump request event.
48static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;
49
50// Access flags for the client on the dump generated event.
51static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
52                                               SYNCHRONIZE;
53
54// Access flags for the client on the mutex.
55static const DWORD kMutexAccess = SYNCHRONIZE;
56
57// Attribute flags for the pipe.
58static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
59                               PIPE_ACCESS_DUPLEX |
60                               FILE_FLAG_OVERLAPPED;
61
62// Mode for the pipe.
63static 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.
72static 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.
76static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
77                                             WT_EXECUTELONGFUNCTION;
78
79static 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
89static 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
97CrashGenerationServer::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.
135CrashGenerationServer::~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
211bool 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.
270void 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.
300void 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.
337void 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.
360void 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.
388void 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.
411void 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.
463void 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.
484void 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.
506void 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.
556void 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
587void CrashGenerationServer::EnterErrorState() {
588  SetEvent(overlapped_.hEvent);
589  server_state_ = IPC_SERVER_STATE_ERROR;
590}
591
592void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) {
593  server_state_ = state;
594}
595
596void CrashGenerationServer::EnterStateImmediately(IPCServerState state) {
597  server_state_ = state;
598
599  if (!SetEvent(overlapped_.hEvent)) {
600    server_state_ = IPC_SERVER_STATE_ERROR;
601  }
602}
603
604bool 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
651bool 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
687bool 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.
713void 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
772bool 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
812void 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
821void 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
836void 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
846void 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
878void 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
899bool 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