Skip to content

Commit

Permalink
Merge pull request #388 from Drewol/feat/crashdump
Browse files Browse the repository at this point in the history
Add crash dumping to the windows build
  • Loading branch information
Drewol authored Aug 29, 2020
2 parents 17acefe + cb8f334 commit bd036d2
Show file tree
Hide file tree
Showing 41 changed files with 8,250 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ if(EMBEDDED)
add_definitions(-DEMBEDDED)
endif()

OPTION(CRASHDUMP "Enable collecting crash dumps" ON)
if(CRASHDUMP)
message("Enabling crash dumps")
add_definitions(-DCRASHDUMP)
endif()

# Include macros
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)

Expand Down
13 changes: 12 additions & 1 deletion Main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ set_output_postfixes(usc-game)

# Target subsystem on windows, set debugging folder
if(MSVC)
set_target_properties(usc-game PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
set_target_properties(usc-game PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS /DEBUG")
set_target_properties(usc-game PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
elseif(NOT APPLE)
target_compile_options(usc-game PUBLIC -Wall -Wextra -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function)
Expand All @@ -81,3 +81,14 @@ target_link_libraries(usc-game nlohmann_json)
target_link_libraries(usc-game ${SDL2_LIBRARY})
target_link_libraries(usc-game ${LibArchive_LIBRARIES})
target_include_directories(usc-game SYSTEM PRIVATE ${LibArchive_INCLUDE_DIRS})

if(WIN32)
target_link_libraries(usc-game
${PROJECT_SOURCE_DIR}/third_party/breakpad/exception_handler.lib
${PROJECT_SOURCE_DIR}/third_party/breakpad/crash_generation_client.lib
${PROJECT_SOURCE_DIR}/third_party/breakpad/common.lib
)
target_include_directories(usc-game PUBLIC ${PROJECT_SOURCE_DIR}/third_party/breakpad/include)
# Always generate pdb
target_compile_options(usc-game PRIVATE /Zi)
endif()
33 changes: 32 additions & 1 deletion Main/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include "GUI/nanovg_lua.h"
#ifdef _WIN32
#include <Windows.h>
#ifdef CRASHDUMP
#include "exception_handler.h"
#include "client_info.h"
#endif
#endif
#include "archive.h"
#include "archive_entry.h"
Expand Down Expand Up @@ -619,7 +623,8 @@ bool Application::m_Init()
{
ProfilerScope $("Application Setup");

Logf("Version: %d.%d.%d", Logger::Severity::Info, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
String version = Utility::Sprintf("%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
Logf("Version: %s", Logger::Severity::Info, version.c_str());

#ifdef EMBEDDED
Log("Embeedded version.");
Expand All @@ -629,6 +634,31 @@ bool Application::m_Init()
Logf("Git commit: %s", Logger::Severity::Info, GIT_COMMIT);
#endif // GIT_COMMIT

#ifdef _WIN32
#ifdef CRASHDUMP
google_breakpad::CustomInfoEntry kCustomInfoEntries[]{
google_breakpad::CustomInfoEntry(L"version", std::wstring(version.begin(), version.end()).c_str()),
#ifdef GIT_COMMIT
google_breakpad::CustomInfoEntry(L"git", L"" GIT_COMMIT),
#else
CustomInfoEntry("git", ""),
#endif
};
google_breakpad::CustomClientInfo custom_info = {kCustomInfoEntries, 2};
//CustomClientInfo custom_info
auto handler = new google_breakpad::ExceptionHandler(
L".\\crash_dumps",
NULL,
NULL,
NULL,
google_breakpad::ExceptionHandler::HANDLER_ALL,
MiniDumpNormal,
(const wchar_t*)nullptr,
&custom_info
);
#endif
#endif

// Must have command line
assert(m_commandLine.size() >= 1);

Expand Down Expand Up @@ -848,6 +878,7 @@ bool Application::m_Init()
Path::CreateDir(Path::Absolute("screenshots"));
Path::CreateDir(Path::Absolute("songs"));
Path::CreateDir(Path::Absolute("replays"));
Path::CreateDir(Path::Absolute("crash_dumps"));

return true;
}
Expand Down
Binary file added third_party/breakpad/common.lib
Binary file not shown.
Binary file added third_party/breakpad/crash_generation_client.lib
Binary file not shown.
Binary file added third_party/breakpad/exception_handler.lib
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// 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_COMMON_AUTO_CRITICAL_SECTION_H__
#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__

#include <windows.h>

namespace google_breakpad {

// Automatically enters the critical section in the constructor and leaves
// the critical section in the destructor.
class AutoCriticalSection {
public:
// Creates a new instance with the given critical section object
// and enters the critical section immediately.
explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs), taken_(false) {
assert(cs_);
Acquire();
}

// Destructor: leaves the critical section.
~AutoCriticalSection() {
if (taken_) {
Release();
}
}

// Enters the critical section. Recursive Acquire() calls are not allowed.
void Acquire() {
assert(!taken_);
EnterCriticalSection(cs_);
taken_ = true;
}

// Leaves the critical section. The caller should not call Release() unless
// the critical seciton has been entered already.
void Release() {
assert(taken_);
taken_ = false;
LeaveCriticalSection(cs_);
}

private:
// Disable copy ctor and operator=.
AutoCriticalSection(const AutoCriticalSection&);
AutoCriticalSection& operator=(const AutoCriticalSection&);

CRITICAL_SECTION* cs_;
bool taken_;
};

} // namespace google_breakpad

#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
181 changes: 181 additions & 0 deletions third_party/breakpad/include/client/windows/common/ipc_protocol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// 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_COMMON_IPC_PROTOCOL_H__
#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__

#include <windows.h>
#include <dbghelp.h>
#include <string>
#include <utility>
#include "common/windows/string_utils-inl.h"
#include "google_breakpad/common/minidump_format.h"

namespace google_breakpad {

// Name/value pair for custom client information.
struct CustomInfoEntry {
// Maximum length for name and value for client custom info.
static const int kNameMaxLength = 64;
static const int kValueMaxLength = 64;

CustomInfoEntry() {
// Putting name and value in initializer list makes VC++ show warning 4351.
set_name(NULL);
set_value(NULL);
}

CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) {
set_name(name_arg);
set_value(value_arg);
}

void set_name(const wchar_t* name_arg) {
if (!name_arg) {
name[0] = L'\0';
return;
}
WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg);
}

void set_value(const wchar_t* value_arg) {
if (!value_arg) {
value[0] = L'\0';
return;
}

WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg);
}

void set(const wchar_t* name_arg, const wchar_t* value_arg) {
set_name(name_arg);
set_value(value_arg);
}

wchar_t name[kNameMaxLength];
wchar_t value[kValueMaxLength];
};

// Constants for the protocol between client and the server.

// Tags sent with each message indicating the purpose of
// the message.
enum MessageTag {
MESSAGE_TAG_NONE = 0,
MESSAGE_TAG_REGISTRATION_REQUEST = 1,
MESSAGE_TAG_REGISTRATION_RESPONSE = 2,
MESSAGE_TAG_REGISTRATION_ACK = 3,
MESSAGE_TAG_UPLOAD_REQUEST = 4
};

struct CustomClientInfo {
const CustomInfoEntry* entries;
size_t count;
};

// Message structure for IPC between crash client and crash server.
struct ProtocolMessage {
ProtocolMessage()
: tag(MESSAGE_TAG_NONE),
id(0),
dump_type(MiniDumpNormal),
thread_id(0),
exception_pointers(NULL),
assert_info(NULL),
custom_client_info(),
dump_request_handle(NULL),
dump_generated_handle(NULL),
server_alive_handle(NULL) {
}

// Creates an instance with the given parameters.
ProtocolMessage(MessageTag arg_tag,
DWORD arg_id,
MINIDUMP_TYPE arg_dump_type,
DWORD* arg_thread_id,
EXCEPTION_POINTERS** arg_exception_pointers,
MDRawAssertionInfo* arg_assert_info,
const CustomClientInfo& custom_info,
HANDLE arg_dump_request_handle,
HANDLE arg_dump_generated_handle,
HANDLE arg_server_alive)
: tag(arg_tag),
id(arg_id),
dump_type(arg_dump_type),
thread_id(arg_thread_id),
exception_pointers(arg_exception_pointers),
assert_info(arg_assert_info),
custom_client_info(custom_info),
dump_request_handle(arg_dump_request_handle),
dump_generated_handle(arg_dump_generated_handle),
server_alive_handle(arg_server_alive) {
}

// Tag in the message.
MessageTag tag;

// The id for this message. This may be either a process id or a crash id
// depending on the type of message.
DWORD id;

// Dump type requested.
MINIDUMP_TYPE dump_type;

// Client thread id pointer.
DWORD* thread_id;

// Exception information.
EXCEPTION_POINTERS** exception_pointers;

// Assert information in case of an invalid parameter or
// pure call failure.
MDRawAssertionInfo* assert_info;

// Custom client information.
CustomClientInfo custom_client_info;

// Handle to signal the crash event.
HANDLE dump_request_handle;

// Handle to check if server is done generating crash.
HANDLE dump_generated_handle;

// Handle to a mutex that becomes signaled (WAIT_ABANDONED)
// if server process goes down.
HANDLE server_alive_handle;

private:
// Disable copy ctor and operator=.
ProtocolMessage(const ProtocolMessage& msg);
ProtocolMessage& operator=(const ProtocolMessage& msg);
};

} // namespace google_breakpad

#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
Loading

0 comments on commit bd036d2

Please sign in to comment.