Skip to content

Commit 413d4e7

Browse files
authored
Minidump improvements (LoneGazebo#11387)
* replace stackwalker * improve minidump
1 parent 856219f commit 413d4e7

17 files changed

+205
-1895
lines changed

CvGameCoreDLL_Expansion2/CustomMods.cpp

+9-14
Original file line numberDiff line numberDiff line change
@@ -616,19 +616,14 @@ int CustomMods::getCivOption(const char* szCiv, const char* szName, int defValue
616616

617617
void CheckSentinel(uint value)
618618
{
619-
if (value == 0xDEADBEEF)
620-
return; //everything ok
621-
622-
CUSTOMLOG("Deserialization Error, check DeserializationCallstack.log\n");
623-
624-
#if defined(STACKWALKER)
625-
FILogFile* pLog=LOGFILEMGR.GetLog( "DeserializationCallstack.log", FILogFile::kDontTimeStamp );
626-
if (pLog)
627-
{
628-
gStackWalker.SetLog(pLog);
629-
gStackWalker.ShowCallstack(5);
630-
gStackWalker.SetLog(NULL);
631-
pLog->Msg("\r\n");
632-
}
619+
if (value == 0xDEADBEEF)
620+
return; //everything ok
621+
622+
CUSTOMLOG("Deserialization Error\n");
623+
624+
#if defined(VPDEBUG)
625+
char debugMsg[256];
626+
sprintf(debugMsg, "Sentinel value mismatch: Expected 0xDEADBEEF, Got 0x%08X\n", value);
627+
OutputDebugString(debugMsg);
633628
#endif
634629
}

CvGameCoreDLL_Expansion2/CvAStar.cpp

+4-17
Original file line numberDiff line numberDiff line change
@@ -415,14 +415,14 @@ bool CvAStar::FindPathWithCurrentConfiguration(int iXstart, int iYstart, int iXd
415415

416416
CvUnit* pUnit = m_sData.iUnitID > 0 ? GET_PLAYER(m_sData.ePlayer).getUnit(m_sData.iUnitID) : NULL;
417417
#if defined(VPDEBUG)
418-
if ( timer.GetDeltaInSeconds()>0.2 && m_sData.ePath==PT_UNIT_MOVEMENT )
418+
if (timer.GetDeltaInSeconds() > 0.2 && m_sData.ePath == PT_UNIT_MOVEMENT)
419419
{
420-
//debug hook
421420
int iStartIndex = GC.getMap().plotNum(m_iXstart, m_iYstart);
422-
if (iStartIndex==giLastStartIndex && iStartIndex>0)
421+
if (iStartIndex == giLastStartIndex && iStartIndex > 0)
423422
{
424423
OutputDebugString("Repeated pathfinding start\n");
425-
gStackWalker.ShowCallstack(5);
424+
// Add debug break point here for investigation during development
425+
ASSERT(false && "Repeated pathfinding detected - investigate call path");
426426
}
427427
giLastStartIndex = iStartIndex;
428428

@@ -435,13 +435,6 @@ bool CvAStar::FindPathWithCurrentConfiguration(int iXstart, int iYstart, int iXd
435435
(100 * m_iProcessedNodes) / iNumPlots, timer.GetDeltaInSeconds() * 1000);
436436
OutputDebugString( msg.c_str() );
437437

438-
#ifdef STACKWALKER
439-
//FILogFile* pLog = LOGFILEMGR.GetLog("PathfinderLongRun.txt", FILogFile::kDontTimeStamp);
440-
//pLog->Msg(msg.c_str());
441-
//gStackWalker.SetLog(pLog);
442-
//gStackWalker.ShowCallstack(5);
443-
//gStackWalker.SetLog(NULL);
444-
#endif
445438
}
446439
#endif
447440

@@ -462,12 +455,6 @@ bool CvAStar::FindPathWithCurrentConfiguration(int iXstart, int iYstart, int iXd
462455
GetName(), m_iXstart, m_iYstart, m_iXdest, m_iYdest, m_sData.ePlayer, m_sData.ePath, m_sData.iFlags).c_str());
463456
}
464457

465-
#ifdef STACKWALKER
466-
gStackWalker.SetLog(pLog);
467-
gStackWalker.ShowCallstack(5);
468-
gStackWalker.SetLog(NULL);
469-
#endif
470-
471458
for (size_t i = 0; i < g_svPathLog.size(); i++)
472459
pLog->Msg(CvString::format("%d,%d,%d,%d,%d,%d,%d,%d\n", g_svPathLog[i].round, g_svPathLog[i].type, g_svPathLog[i].x, g_svPathLog[i].y,
473460
g_svPathLog[i].kc, g_svPathLog[i].hc, g_svPathLog[i].t, g_svPathLog[i].m).c_str());

CvGameCoreDLL_Expansion2/CvGameCoreDLL_Expansion2.vs2010.vcxproj

+1-5
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
<ClCompile>
6565
<AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
6666
<AdditionalIncludeDirectories>$(SolutionDir)CvWorldBuilderMap\include\;$(SolutionDir)CvGameCoreDLLUtil\include\;$(SolutionDir)CvLocalization\include\;$(SolutionDir)CvGameDatabase\include\;$(SolutionDir)FirePlace\include\;$(SolutionDir)FirePlace\include\FireWorks\;$(SolutionDir)ThirdPartyLibs\Lua51\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
67-
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;CVGAMECOREDLL_EXPORTS;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;STACKWALKER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
67+
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;CVGAMECOREDLL_EXPORTS;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
6868
<ExceptionHandling>
6969
</ExceptionHandling>
7070
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -157,9 +157,6 @@
157157
<ClCompile Include="CvDistanceMap.cpp" />
158158
<ClCompile Include="CvGreatPersonInfo.cpp" />
159159
<ClCompile Include="CvTargeting.cpp" />
160-
<ClCompile Include="stackwalker\StackWalker.cpp">
161-
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">NotUsing</PrecompiledHeader>
162-
</ClCompile>
163160
<ClCompile Include="_precompile.cpp">
164161
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">Create</PrecompiledHeader>
165162
</ClCompile>
@@ -331,7 +328,6 @@
331328
<ClInclude Include="CvCorporationClasses.h" />
332329
<ClInclude Include="CvContractClasses.h" />
333330
<ClInclude Include="HHMods.h" />
334-
<ClInclude Include="stackwalker\stackwalker.h" />
335331
<ClInclude Include="TContainer.h" />
336332
<ClInclude Include="CustomMods.h" />
337333
<ClInclude Include="CvAchievementUnlocker.h" />

CvGameCoreDLL_Expansion2/CvGameCoreDLL_Expansion2.vs2010.vcxproj.filters

-6
Original file line numberDiff line numberDiff line change
@@ -527,9 +527,6 @@
527527
<ClCompile Include="CvContractClasses.cpp">
528528
<Filter>Source Files</Filter>
529529
</ClCompile>
530-
<ClCompile Include="stackwalker\StackWalker.cpp">
531-
<Filter>Source Files</Filter>
532-
</ClCompile>
533530
</ItemGroup>
534531
<ItemGroup>
535532
<ClInclude Include="banned.h">
@@ -1078,9 +1075,6 @@
10781075
<ClInclude Include="CvContractClasses.h">
10791076
<Filter>Header Files</Filter>
10801077
</ClInclude>
1081-
<ClInclude Include="stackwalker\stackwalker.h">
1082-
<Filter>Header Files</Filter>
1083-
</ClInclude>
10841078
</ItemGroup>
10851079
<ItemGroup>
10861080
<ResourceCompile Include="CvGameCoreDLL.rc" />

CvGameCoreDLL_Expansion2/CvGameCoreDLL_Expansion2.vs2012.vcxproj

+1-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<ClCompile>
6666
<AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
6767
<AdditionalIncludeDirectories>$(SolutionDir)CvWorldBuilderMap\include\;$(SolutionDir)CvGameCoreDLLUtil\include\;$(SolutionDir)CvLocalization\include\;$(SolutionDir)CvGameDatabase\include\;$(SolutionDir)FirePlace\include\;$(SolutionDir)FirePlace\include\FireWorks\;$(SolutionDir)ThirdPartyLibs\Lua51\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
68-
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;EXTERNAL_PAUSING;STACKWALKER;CVGAMECOREDLL_EXPORTS;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
68+
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;EXTERNAL_PAUSING;CVGAMECOREDLL_EXPORTS;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
6969
<ExceptionHandling>
7070
</ExceptionHandling>
7171
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -159,10 +159,6 @@
159159
<ClCompile Include="CvDistanceMap.cpp" />
160160
<ClCompile Include="CvGreatPersonInfo.cpp" />
161161
<ClCompile Include="CvTargeting.cpp" />
162-
<ClCompile Include="stackwalker\StackWalker.cpp">
163-
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">NotUsing</PrecompiledHeader>
164-
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ModRelease|Win32'">NotUsing</PrecompiledHeader>
165-
</ClCompile>
166162
<ClCompile Include="_precompile.cpp">
167163
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">Create</PrecompiledHeader>
168164
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ModRelease|Win32'">Create</PrecompiledHeader>

CvGameCoreDLL_Expansion2/CvGameCoreDLL_Expansion2.vs2015 .vcxproj

+1-5
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
<ClCompile>
7272
<AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
7373
<AdditionalIncludeDirectories>C:\Program Files (x86)\Visual Leak Detector\include;$(SolutionDir)CvWorldBuilderMap\include\;$(SolutionDir)CvGameCoreDLLUtil\include\;$(SolutionDir)CvLocalization\include\;$(SolutionDir)CvGameDatabase\include\;$(SolutionDir)FirePlace\include\;$(SolutionDir)FirePlace\include\FireWorks\;$(SolutionDir)ThirdPartyLibs\Lua51\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
74-
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;CVGAMECOREDLL_EXPORTS;EXTERNAL_PAUSING;STACKWALKER;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
74+
<PreprocessorDefinitions>FXS_IS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;CVGAMECOREDLL_EXPORTS;EXTERNAL_PAUSING;FINAL_RELEASE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
7575
<ExceptionHandling>SyncCThrow</ExceptionHandling>
7676
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
7777
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -173,10 +173,6 @@
173173
<ClCompile Include="CvDistanceMap.cpp" />
174174
<ClCompile Include="CvGreatPersonInfo.cpp" />
175175
<ClCompile Include="CvTargeting.cpp" />
176-
<ClCompile Include="stackwalker\StackWalker.cpp">
177-
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">NotUsing</PrecompiledHeader>
178-
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ModRelease|Win32'">NotUsing</PrecompiledHeader>
179-
</ClCompile>
180176
<ClCompile Include="_precompile.cpp">
181177
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Mod|Win32'">Create</PrecompiledHeader>
182178
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ModRelease|Win32'">Create</PrecompiledHeader>

CvGameCoreDLL_Expansion2/CvGlobals.cpp

+122-39
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@
4444
#include "CvDllUnit.h"
4545

4646
#if defined(MOD_DEBUG_MINIDUMP)
47+
#ifdef WIN32
48+
#include "../commit_id.inc"
4749
#include <dbghelp.h>
48-
#endif
50+
#endif // WIN32
51+
#endif // defined(MOD_DEBUG_MINIDUMP)
4952

5053
// must be included after all other headers
5154
#include "LintFree.h"
@@ -2408,11 +2411,6 @@ CvGlobals::~CvGlobals()
24082411
uninit();
24092412
}
24102413

2411-
#ifdef STACKWALKER
2412-
MyStackWalker gStackWalker;
2413-
lua_State* gLuaState = NULL;
2414-
#endif
2415-
24162414
//cannot use GC.getGame().getActivePlayer() in observer mode
24172415
PlayerTypes GetCurrentPlayer()
24182416
{
@@ -2426,6 +2424,7 @@ PlayerTypes GetCurrentPlayer()
24262424
}
24272425

24282426
#if defined(MOD_DEBUG_MINIDUMP)
2427+
#ifdef WIN32
24292428
/************************************************************************************************/
24302429
/* MINIDUMP_MOD 04/10/11 terkhen */
24312430
/* See http://www.debuginfo.com/articles/effminidumps.html */
@@ -2434,51 +2433,131 @@ PlayerTypes GetCurrentPlayer()
24342433
/* See http://forums.civfanatics.com/showthread.php?t=498919 */
24352434
/************************************************************************************************/
24362435

2437-
#pragma comment (lib, "dbghelp.lib")
2438-
void CreateMiniDump(EXCEPTION_POINTERS *pep)
2439-
{
2440-
#ifdef STACKWALKER
2441-
{
2442-
/* Try to log the callstack */
2443-
FILogFile* pLog=LOGFILEMGR.GetLog( "Callstack.log", FILogFile::kDontTimeStamp );
2444-
if (pLog)
2445-
{
2446-
pLog->Msg("Gamecore Callstack\n");
2447-
2448-
gStackWalker.SetLog(pLog);
2449-
gStackWalker.ShowCallstack(INT_MAX, GetCurrentThread(), pep ? pep->ContextRecord : NULL );
2450-
gStackWalker.SetLog(NULL);
2451-
2452-
pLog->Msg("\nLua Callstack\n");
2453-
if (gLuaState)
2454-
LuaSupport::DumpCallStack(gLuaState,pLog);
2455-
2456-
pLog->Close();
2436+
#pragma comment(lib, "dbghelp.lib")
2437+
void CreateMiniDump(EXCEPTION_POINTERS* pep)
2438+
{
2439+
// Initialize debug symbols
2440+
HANDLE hProcess = GetCurrentProcess();
2441+
SymInitialize(hProcess, NULL, TRUE);
2442+
2443+
// Get timestamp
2444+
SYSTEMTIME st;
2445+
GetLocalTime(&st);
2446+
TCHAR szTimestamp[64];
2447+
_stprintf_s(szTimestamp, sizeof(szTimestamp) / sizeof(TCHAR),
2448+
_T("%04d%02d%02d_%02d%02d%02d"),
2449+
st.wYear, st.wMonth, st.wDay,
2450+
st.wHour, st.wMinute, st.wSecond);
2451+
2452+
// Extract just version number and commit hash from CURRENT_GAMECORE_VERSION
2453+
char shortVersion[64];
2454+
const char* fullVersion = CURRENT_GAMECORE_VERSION;
2455+
const char* versionStart = strchr(fullVersion, '-');
2456+
if (versionStart) {
2457+
versionStart++; // Skip the '-'
2458+
const char* spaceAfterVersion = strchr(versionStart, ' ');
2459+
if (spaceAfterVersion) {
2460+
// Copy just the version number (e.g. "4.16")
2461+
size_t versionLen = spaceAfterVersion - versionStart;
2462+
strncpy_s(shortVersion, sizeof(shortVersion), versionStart, versionLen);
2463+
shortVersion[versionLen] = '\0';
2464+
2465+
// Add the commit hash if present
2466+
const char* commitHash = spaceAfterVersion + 1;
2467+
const char* nextSpace = strchr(commitHash, ' ');
2468+
if (nextSpace) {
2469+
strcat_s(shortVersion, sizeof(shortVersion), "_");
2470+
strncat_s(shortVersion, sizeof(shortVersion), commitHash, nextSpace - commitHash);
2471+
}
24572472
}
24582473
}
2474+
else {
2475+
strcpy_s(shortVersion, sizeof(shortVersion), "unknown");
2476+
}
2477+
2478+
// Generate dump filename with version, commit hash and build type
2479+
TCHAR szDumpPath[MAX_PATH];
2480+
_stprintf_s(szDumpPath, MAX_PATH, _T("CvMiniDump_%s_%hs_%s.dmp"),
2481+
szTimestamp,
2482+
shortVersion,
2483+
#ifdef VPDEBUG
2484+
_T("Debug")
2485+
#else
2486+
_T("Release")
24592487
#endif
2488+
);
2489+
2490+
HANDLE hFile = CreateFile(szDumpPath, GENERIC_READ | GENERIC_WRITE,
2491+
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
24602492

2461-
/* Open a file to store the minidump. */
2462-
HANDLE hFile = CreateFile(_T("CvMiniDump.dmp"), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2463-
if((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) {
2464-
_tprintf(_T("CreateFile failed. Error: %lu \n"), GetLastError());
2493+
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) {
24652494
return;
24662495
}
24672496

2468-
/* Create the minidump. */
24692497
MINIDUMP_EXCEPTION_INFORMATION mdei;
2470-
mdei.ThreadId = GetCurrentThreadId();
2471-
mdei.ExceptionPointers = pep;
2472-
mdei.ClientPointers = FALSE;
2498+
mdei.ThreadId = GetCurrentThreadId();
2499+
mdei.ExceptionPointers = pep;
2500+
mdei.ClientPointers = FALSE;
2501+
2502+
// Configure dump type based on build
2503+
MINIDUMP_TYPE mdt;
2504+
#ifdef VPDEBUG
2505+
OutputDebugString(_T("Creating Debug minidump\n"));
2506+
mdt = (MINIDUMP_TYPE)(
2507+
MiniDumpWithFullMemory | // Complete memory snapshot
2508+
MiniDumpWithFullMemoryInfo | // Memory state information
2509+
MiniDumpWithHandleData | // Handle usage
2510+
MiniDumpWithUnloadedModules | // Track unloaded DLLs
2511+
MiniDumpWithThreadInfo | // Extended thread information
2512+
MiniDumpWithProcessThreadData | // Process thread data
2513+
MiniDumpWithCodeSegs | // Code segments
2514+
MiniDumpWithDataSegs | // Data segments
2515+
MiniDumpWithPrivateReadWriteMemory | // Private memory
2516+
MiniDumpWithFullAuxiliaryState | // Auxiliary state (handles, GDI objects)
2517+
MINIDUMP_TYPE(0x00000040) | // MiniDumpWithTokenInformation
2518+
MINIDUMP_TYPE(0x00000400) | // MiniDumpWithPrivateWriteCopyMemory
2519+
MINIDUMP_TYPE(0x00020000) | // MiniDumpIgnoreInaccessibleMemory
2520+
MiniDumpWithIndirectlyReferencedMemory | // Memory referenced by locals
2521+
MINIDUMP_TYPE(0x00000800) // MiniDumpWithModuleHeaders
2522+
);
2523+
#else
2524+
OutputDebugString(_T("Creating Release minidump\n"));
2525+
mdt = (MINIDUMP_TYPE)(
2526+
MiniDumpNormal | // Basic info
2527+
MiniDumpWithThreadInfo | // Thread information
2528+
MINIDUMP_TYPE(0x00020000) // MiniDumpIgnoreInaccessibleMemory
2529+
);
2530+
#endif
2531+
2532+
// Add version info
2533+
MINIDUMP_USER_STREAM_INFORMATION additional_streams;
2534+
MINIDUMP_USER_STREAM user_streams[1];
2535+
char version_info[256];
2536+
2537+
sprintf_s(version_info, sizeof(version_info),
2538+
"Version: %s", CURRENT_GAMECORE_VERSION);
2539+
2540+
user_streams[0].Type = 0x00000003; // MinidumpCommentStreamA
2541+
user_streams[0].Buffer = version_info;
2542+
user_streams[0].BufferSize = static_cast<ULONG>(strlen(version_info) + 1);
24732543

2474-
MINIDUMP_TYPE mdt = MiniDumpNormal;
2544+
additional_streams.UserStreamCount = 1;
2545+
additional_streams.UserStreamArray = user_streams;
24752546

2476-
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, mdt, (pep != NULL) ? &mdei : NULL, NULL, NULL);
2547+
// Write the dump
2548+
MiniDumpWriteDump(
2549+
GetCurrentProcess(),
2550+
GetCurrentProcessId(),
2551+
hFile,
2552+
mdt,
2553+
(pep != NULL) ? &mdei : NULL,
2554+
&additional_streams,
2555+
NULL);
24772556

24782557
CloseHandle(hFile);
24792558
}
24802559

2481-
LONG WINAPI CustomFilter(EXCEPTION_POINTERS *ExceptionInfo)
2560+
LONG WINAPI CustomFilter(EXCEPTION_POINTERS* ExceptionInfo)
24822561
{
24832562
CreateMiniDump(ExceptionInfo);
24842563
return EXCEPTION_EXECUTE_HANDLER;
@@ -2491,10 +2570,14 @@ LONG WINAPI CustomFilter(EXCEPTION_POINTERS *ExceptionInfo)
24912570
void CvGlobals::init()
24922571
{
24932572
#if defined(MOD_DEBUG_MINIDUMP)
2494-
/* Enable our custom exception that will write the minidump for us. */
24952573
SetUnhandledExceptionFilter(CustomFilter);
2496-
CUSTOMLOG("MiniDump exception handler installed");
2574+
#ifdef VPDEBUG
2575+
OutputDebugString(_T("Debug MiniDump handler installed\n"));
2576+
#else
2577+
OutputDebugString(_T("Release MiniDump handler installed\n"));
24972578
#endif
2579+
#endif // WIN32
2580+
#endif // defined(MOD_DEBUG_MINIDUMP)
24982581

24992582
//
25002583
// These vars are used to initialize the globals.

0 commit comments

Comments
 (0)