summaryrefslogtreecommitdiffstats
blob: 0ea90e5100fa672ee9a8d6baf02063a707d2d1f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__

#include <list>
#include <string>
#include "client/windows/common/ipc_protocol.h"
#include "client/windows/crash_generation/minidump_generator.h"
#include "common/scoped_ptr.h"

namespace google_breakpad {
class ClientInfo;

// Abstraction for server side implementation of out-of-process crash
// generation protocol for Windows platform only. It generates Windows
// minidump files for client processes that request dump generation. When
// the server is requested to start listening for clients (by calling the
// Start method), it creates a named pipe and waits for the clients to
// register. In response, it hands them event handles that the client can
// signal to request dump generation. When the clients request dump
// generation in this way, the server generates Windows minidump files.
class CrashGenerationServer {
 public:
  typedef void (*OnClientConnectedCallback)(void* context,
                                            const ClientInfo* client_info);

  typedef void (*OnClientDumpRequestCallback)(void* context,
                                              const ClientInfo* client_info,
                                              const std::wstring* file_path);

  typedef void (*OnClientExitedCallback)(void* context,
                                         const ClientInfo* client_info);

  typedef void (*OnClientUploadRequestCallback)(void* context,
                                                const DWORD crash_id);

  // Creates an instance with the given parameters.
  //
  // Parameter pipe_name: Name of the Windows named pipe
  // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass
  //     NULL to use default security on the pipe. By default, the pipe created
  //     allows Local System, Administrators and the Creator full control and
  //     the Everyone group read access on the pipe.
  // Parameter connect_callback: Callback for a new client connection.
  // Parameter connect_context: Context for client connection callback.
  // Parameter crash_callback: Callback for a client crash dump request.
  // Parameter crash_context: Context for client crash dump request callback.
  // Parameter exit_callback: Callback for client process exit.
  // Parameter exit_context: Context for client exit callback.
  // Parameter generate_dumps: Whether to automatically generate dumps.
  // Client code of this class might want to generate dumps explicitly in the
  // crash dump request callback. In that case, false can be passed for this
  // parameter.
  // Parameter dump_path: Path for generating dumps; required only if true is
  // passed for generateDumps parameter; NULL can be passed otherwise.
  CrashGenerationServer(const std::wstring& pipe_name,
                        SECURITY_ATTRIBUTES* pipe_sec_attrs,
                        OnClientConnectedCallback connect_callback,
                        void* connect_context,
                        OnClientDumpRequestCallback dump_callback,
                        void* dump_context,
                        OnClientExitedCallback exit_callback,
                        void* exit_context,
                        OnClientUploadRequestCallback upload_request_callback,
                        void* upload_context,
                        bool generate_dumps,
                        const std::wstring* dump_path);

  ~CrashGenerationServer();

  // Performs initialization steps needed to start listening to clients. Upon
  // successful return clients may connect to this server's pipe.
  //
  // Returns true if initialization is successful; false otherwise.
  bool Start();

  void pre_fetch_custom_info(bool do_pre_fetch) {
    pre_fetch_custom_info_ = do_pre_fetch;
  }

 private:
  // Various states the client can be in during the handshake with
  // the server.
  enum IPCServerState {
    // Server starts in this state.
    IPC_SERVER_STATE_UNINITIALIZED,

    // Server is in error state and it cannot serve any clients.
    IPC_SERVER_STATE_ERROR,

    // Server starts in this state.
    IPC_SERVER_STATE_INITIAL,

    // Server has issued an async connect to the pipe and it is waiting
    // for the connection to be established.
    IPC_SERVER_STATE_CONNECTING,

    // Server is connected successfully.
    IPC_SERVER_STATE_CONNECTED,

    // Server has issued an async read from the pipe and it is waiting for
    // the read to finish.
    IPC_SERVER_STATE_READING,

    // Server is done reading from the pipe.
    IPC_SERVER_STATE_READ_DONE,

    // Server has issued an async write to the pipe and it is waiting for
    // the write to finish.
    IPC_SERVER_STATE_WRITING,

    // Server is done writing to the pipe.
    IPC_SERVER_STATE_WRITE_DONE,

    // Server has issued an async read from the pipe for an ack and it
    // is waiting for the read to finish.
    IPC_SERVER_STATE_READING_ACK,

    // Server is done writing to the pipe and it is now ready to disconnect
    // and reconnect.
    IPC_SERVER_STATE_DISCONNECTING
  };

  //
  // Helper methods to handle various server IPC states.
  //
  void HandleErrorState();
  void HandleInitialState();
  void HandleConnectingState();
  void HandleConnectedState();
  void HandleReadingState();
  void HandleReadDoneState();
  void HandleWritingState();
  void HandleWriteDoneState();
  void HandleReadingAckState();
  void HandleDisconnectingState();

  // Prepares reply for a client from the given parameters.
  bool PrepareReply(const ClientInfo& client_info,
                    ProtocolMessage* reply) const;

  // Duplicates various handles in the ClientInfo object for the client
  // process and stores them in the given ProtocolMessage instance. If
  // creating any handle fails, ProtocolMessage will contain the handles
  // already created successfully, which should be closed by the caller.
  bool CreateClientHandles(const ClientInfo& client_info,
                           ProtocolMessage* reply) const;

  // Response to the given client. Return true if all steps of
  // responding to the client succeed, false otherwise.
  bool RespondToClient(ClientInfo* client_info);

  // Handles a connection request from the client.
  void HandleConnectionRequest();

  // Handles a dump request from the client.
  void HandleDumpRequest(const ClientInfo& client_info);

  // Callback for pipe connected event.
  static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait);

  // Callback for a dump request.
  static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait);

  // Callback for client process exit event.
  static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait);

  // Handles client process exit.
  void HandleClientProcessExit(ClientInfo* client_info);

  // Adds the given client to the list of registered clients.
  bool AddClient(ClientInfo* client_info);

  // Generates dump for the given client.
  bool GenerateDump(const ClientInfo& client, std::wstring* dump_path);

  // Puts the server in a permanent error state and sets a signal such that
  // the state will be immediately entered after the current state transition
  // is complete.
  void EnterErrorState();

  // Puts the server in the specified state and sets a signal such that the
  // state is immediately entered after the current state transition is
  // complete.
  void EnterStateImmediately(IPCServerState state);

  // Puts the server in the specified state. No signal will be set, so the state
  // transition will only occur when signaled manually or by completion of an
  // asynchronous IO operation.
  void EnterStateWhenSignaled(IPCServerState state);

  // Sync object for thread-safe access to the shared list of clients.
  CRITICAL_SECTION sync_;

  // List of clients.
  std::list<ClientInfo*> clients_;

  // Pipe name.
  std::wstring pipe_name_;

  // Pipe security attributes
  SECURITY_ATTRIBUTES* pipe_sec_attrs_;

  // Handle to the pipe used for handshake with clients.
  HANDLE pipe_;

  // Pipe wait handle.
  HANDLE pipe_wait_handle_;

  // Handle to server-alive mutex.
  HANDLE server_alive_handle_;

  // Callback for a successful client connection.
  OnClientConnectedCallback connect_callback_;

  // Context for client connected callback.
  void* connect_context_;

  // Callback for a client dump request.
  OnClientDumpRequestCallback dump_callback_;

  // Context for client dump request callback.
  void* dump_context_;

  // Callback for client process exit.
  OnClientExitedCallback exit_callback_;

  // Context for client process exit callback.
  void* exit_context_;

  // Callback for upload request.
  OnClientUploadRequestCallback upload_request_callback_;

  // Context for upload request callback.
  void* upload_context_;

  // Whether to generate dumps.
  bool generate_dumps_;

  // Wether to populate custom information up-front.
  bool pre_fetch_custom_info_;

  // The dump path for the server.
  const std::wstring dump_path_;

  // State of the server in performing the IPC with the client.
  // Note that since we restrict the pipe to one instance, we
  // only need to keep one state of the server. Otherwise, server
  // would have one state per client it is talking to.
  IPCServerState server_state_;

  // Whether the server is shutting down.
  bool shutting_down_;

  // Overlapped instance for async I/O on the pipe.
  OVERLAPPED overlapped_;

  // Message object used in IPC with the client.
  ProtocolMessage msg_;

  // Client Info for the client that's connecting to the server.
  ClientInfo* client_info_;

  // Disable copy ctor and operator=.
  CrashGenerationServer(const CrashGenerationServer& crash_server);
  CrashGenerationServer& operator=(const CrashGenerationServer& crash_server);
};

}  // namespace google_breakpad

#endif  // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__