handlesys: Output allocation timestamp during panic (#1110)

* Track Handle creation time

* Move ConVar operations outside of loop

* We support bee's here

* Catch windows awfulness

* Prevent Character Truncation

* Add timestamp info to memory leak dump

* Remove last line and adjust new leak dump output

* KyleS fixes

* Fixed width output

* Create invalid parameter failure redirection helper

* Fix rebase regression

* Update sm_invalidparamhandler.h

* Update HandleSys.cpp

* Update HandleSys.cpp

* Update HandleSys.cpp

Co-authored-by: Kyle Sanderson <[email protected]>
This commit is contained in:
Headline
2020-07-09 18:21:45 -07:00
committed by GitHub
co-authored by Kyle Sanderson
parent a065773b6d
commit 2653a450fc
6 changed files with 174 additions and 79 deletions
+68 -6
View File
@@ -30,6 +30,7 @@
*/
#include "HandleSys.h"
#include <time.h>
#include <assert.h>
#include <string.h>
#include "common_logic.h"
@@ -38,10 +39,18 @@
#include "PluginSys.h"
#include <am-string.h>
#include <bridge/include/ILogger.h>
#include <bridge/include/CoreProvider.h>
#include <ISourceMod.h>
#include "sm_platform.h"
#ifdef PLATFORM_WINDOWS
#include "sm_invalidparamhandler.h"
#endif
HandleSystem g_HandleSys;
QHandle *ignore_handle;
extern ConVar *g_datetime_format;
inline HandleType_t TypeParent(HandleType_t type)
{
@@ -430,7 +439,7 @@ Handle_t HandleSystem::CreateHandleInt(HandleType_t type,
pHandle->object = object;
pHandle->clone = 0;
pHandle->timestamp = g_pSM->GetAdjustedTime();
return handle;
}
@@ -1014,6 +1023,8 @@ bool HandleSystem::TryAndFreeSomeHandles()
unsigned int * pCount = new unsigned int[HANDLESYS_TYPEARRAY_SIZE+1];
memset(pCount, 0, ((HANDLESYS_TYPEARRAY_SIZE + 1) * sizeof(unsigned int)));
const QHandle *oldest = nullptr;
const QHandle *newest = nullptr;
for (unsigned int i = 1; i <= m_HandleTail; ++i)
{
const QHandle &Handle = m_Handles[i];
@@ -1030,6 +1041,15 @@ bool HandleSystem::TryAndFreeSomeHandles()
highest_index = ((Handle.type) + 1);
}
if (!oldest || oldest->timestamp > Handle.timestamp)
{
oldest = &Handle;
}
if (!newest || newest->timestamp < Handle.timestamp)
{
newest = &Handle;
}
if (Handle.clone != 0)
{
continue;
@@ -1057,7 +1077,33 @@ bool HandleSystem::TryAndFreeSomeHandles()
HANDLE_LOG_VERY_BAD("Type\t%-20.20s|\tCount\t%u", pTypeName, pCount[i]);
}
const char *fmt = bridge->GetCvarString(g_datetime_format);
char oldstamp[256], newstamp[256]; // 256 should be more than enough
// scope for InvalidParameterHandler
{
#ifdef PLATFORM_WINDOWS
InvalidParameterHandler p;
#endif
size_t written = strftime(oldstamp, sizeof(oldstamp), fmt, localtime(&oldest->timestamp));
if (!written)
{
ke::SafeStrcpy(oldstamp, sizeof(oldstamp), "INVALID");
}
written = strftime(newstamp, sizeof(newstamp), fmt, localtime(&newest->timestamp));
if (!written)
{
ke::SafeStrcpy(newstamp, sizeof(newstamp), "INVALID");
}
}
HANDLE_LOG_VERY_BAD("--------------------------------------------------------------------------");
HANDLE_LOG_VERY_BAD("Oldest Living Handle: %s created at %s", m_Types[oldest->type].name->c_str(), oldstamp);
HANDLE_LOG_VERY_BAD("Newest Living Handle: %s created at %s", m_Types[newest->type].name->c_str(), newstamp);
HANDLE_LOG_VERY_BAD("-- Approximately %d bytes of memory are in use by (%u) Handles.\n", total_size, total);
delete [] pCount;
@@ -1081,8 +1127,10 @@ static void rep(const HandleReporter &fn, const char *fmt, ...)
void HandleSystem::Dump(const HandleReporter &fn)
{
unsigned int total_size = 0;
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep(fn, "--------------------------------------------------------------------------");
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", "Handle", "Owner", "Type", "Memory", "Time Created");
rep(fn, "---------------------------------------------------------------------------------------------");
const char *fmt = bridge->GetCvarString(g_datetime_format);
for (unsigned int i = 1; i <= m_HandleTail; i++)
{
if (m_Handles[i].set != HandleSet_Used)
@@ -1150,19 +1198,33 @@ void HandleSystem::Dump(const HandleReporter &fn)
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
}
char date[256]; // 256 should be more than enough
size_t written = 0;
// scope for InvalidParameterHandler
{
#ifdef PLATFORM_WINDOWS
InvalidParameterHandler p;
#endif
written = strftime(date, sizeof(date), fmt, localtime(&m_Handles[i].timestamp));
}
if (!written)
{
ke::SafeStrcpy(date, sizeof(date), "INVALID");
}
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|| !bresult)
{
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", index, owner, type, "-1", date);
}
else
{
char buffer[32];
ke::SafeSprintf(buffer, sizeof(buffer), "%d", size);
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", index, owner, type, buffer, date);
total_size += size;
}
}
rep(fn, "-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
}