// 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 #include #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 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__