From b73bb9cfaa954441c2ad96ea7dc7416aaad09534 Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Wed, 20 Feb 2013 18:27:07 +0100 Subject: [PATCH] Win32: optionally embed a build ID into crash dumps/minidump files In order to get an embedded build ID, add a new CMake cache variable named OC_BUILD_ID. This variable can contain an arbitrary string, but it is suggested that you use a hierarchical string starting with your DNS domain, reversed, as in "com.example.openclonk.arbitrarystring" (think java packages). --- Makefile.am | 3 ++- src/C4Version.h.in | 4 ++++ src/platform/C4CrashHandlerWin32.cpp | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index d7469e88a..e5f2de62a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,7 +76,8 @@ do_subst = sed -e 's,[@]C4PROJECT[@],'"$$(sed -n 's/SET(C4PROJECT\s\+"\(.\+\)")/ -e 's,[@]C4XVER3[@],'"$$(sed -n 's/SET(C4XVER3\s\+\(.\+\))/\1/ p' $(srcdir)/Version.txt)"',g' \ -e 's,[@]C4XVER4[@],'"$$(sed -n 's/SET(C4XVER4\s\+\(.\+\))/\1/ p' $(srcdir)/Version.txt)"',g' \ -e 's,[@]C4VERSIONBUILDNAME[@],'"$$(sed -n 's/SET(C4VERSIONBUILDNAME\s\+"\(.\+\)")/\1/ p' $(srcdir)/Version.txt)"',g' \ - -e 's,[@]C4VERSIONEXTRA[@],'"$$(sed -n 's/SET(C4VERSIONEXTRA\s\+"\(.\+\)")/\1/ p' $(srcdir)/Version.txt)"',g' + -e 's,[@]C4VERSIONEXTRA[@],'"$$(sed -n 's/SET(C4VERSIONEXTRA\s\+"\(.\+\)")/\1/ p' $(srcdir)/Version.txt)"',g' \ + -e 's,[@]OC_BUILD_ID[@],,g' C4Version.h: $(srcdir)/src/C4Version.h.in $(srcdir)/Version.txt $(do_subst) < $< > $@ diff --git a/src/C4Version.h.in b/src/C4Version.h.in index 98da0caa0..6900c6b97 100644 --- a/src/C4Version.h.in +++ b/src/C4Version.h.in @@ -4,6 +4,7 @@ * Copyright (c) 2001-2002, 2010 Peter Wortmann * Copyright (c) 2005, 2009-2010 Günther Brammer * Copyright (c) 2009 Matthes Bender + * Copyright (c) 2013 Nicolas Hake * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de * * Portions might be copyrighted by other authors who have contributed @@ -71,4 +72,7 @@ #define C4VERSION C4XVERTOC4XVERS(C4XVER1) "." C4XVERTOC4XVERS(C4XVER2) "." C4XVERTOC4XVERS(C4XVER3) " [" C4XVER4S "]" C4VERSIONEXTRA C4BUILDOPT #endif +// if this is set, add a build identifier to the logs and crash dumps +#define OC_BUILD_ID "@OC_BUILD_ID@" + #endif diff --git a/src/platform/C4CrashHandlerWin32.cpp b/src/platform/C4CrashHandlerWin32.cpp index a3c862090..93ffb7457 100644 --- a/src/platform/C4CrashHandlerWin32.cpp +++ b/src/platform/C4CrashHandlerWin32.cpp @@ -30,6 +30,7 @@ #ifdef HAVE_DBGHELP // Dump generation on crash +#include #include #include #include @@ -80,7 +81,12 @@ namespace { #else # define POINTER_FORMAT "0x%" POINTER_FORMAT_SUFFIX #endif - + + LOG_STATIC_TEXT("**********************************************************************\n"); + LOG_STATIC_TEXT("* UNHANDLED EXCEPTION\n"); + if (OC_BUILD_ID[0] != '\0') + LOG_STATIC_TEXT("* Build Identifier: " OC_BUILD_ID "\n"); + LOG_STATIC_TEXT("**********************************************************************\n"); // Log exception type switch (exc->ExceptionRecord->ExceptionCode) { @@ -349,6 +355,11 @@ namespace { } LONG WINAPI GenerateDump(EXCEPTION_POINTERS* pExceptionPointers) { + enum + { + MDST_BuildId = LastReservedStream + 1 + }; + if (!FirstCrash) return EXCEPTION_EXECUTE_HANDLER; FirstCrash = false; @@ -359,12 +370,23 @@ LONG WINAPI GenerateDump(EXCEPTION_POINTERS* pExceptionPointers) // Write dump (human readable format) SafeTextDump(pExceptionPointers, GetLogFD()); + MINIDUMP_USER_STREAM_INFORMATION user_stream_info = {0}; + MINIDUMP_USER_STREAM user_stream = {0}; + if (OC_BUILD_ID[0] != '\0') + { + user_stream.Type = MDST_BuildId; + user_stream.Buffer = &OC_BUILD_ID; + user_stream.BufferSize = sizeof(OC_BUILD_ID); + user_stream_info.UserStreamCount = 1; + user_stream_info.UserStreamArray = &user_stream; + } + MINIDUMP_EXCEPTION_INFORMATION ExpParam; ExpParam.ThreadId = GetCurrentThreadId(); ExpParam.ExceptionPointers = pExceptionPointers; ExpParam.ClientPointers = true; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - file, MiniDumpNormal, &ExpParam, NULL, NULL); + file, MiniDumpNormal, &ExpParam, &user_stream_info, NULL); CloseHandle(file); // Pass exception