Move sm_dump_handles to core/logic.

This commit is contained in:
David Anderson 2015-09-11 01:33:43 -07:00
parent c853050265
commit 168b779786
8 changed files with 74 additions and 82 deletions

View File

@ -35,7 +35,7 @@ namespace SourceMod {
// Add 1 to the RHS of this expression to bump the intercom file
// This is to prevent mismatching core/logic binaries
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 52;
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 53;
} // namespace SourceMod

View File

@ -68,7 +68,6 @@ struct sm_logic_t
IDebugListener *debugger;
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
void (*AddNatives)(sp_nativeinfo_t *natives);
void (*DumpHandles)(void (*dumpfn)(const char *fmt, ...));
void (*RegisterProfiler)(IProfilingTool *tool);
void (*OnRootCommand)(const ICommandArgs *args);
IDataPack * (*CreateDataPack)();

View File

@ -1066,11 +1066,23 @@ bool HandleSystem::TryAndFreeSomeHandles()
return scripts->UnloadPlugin(highest_owner);
}
void HandleSystem::Dump(HANDLE_REPORTER rep)
static void rep(const HandleReporter &fn, const char *fmt, ...)
{
va_list ap;
char buffer[1024];
va_start(ap, fmt);
ke::SafeVsprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
fn(buffer);
}
void HandleSystem::Dump(const HandleReporter &fn)
{
unsigned int total_size = 0;
rep("%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep("--------------------------------------------------------------------------");
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep(fn, "--------------------------------------------------------------------------");
for (unsigned int i = 1; i <= m_HandleTail; i++)
{
if (m_Handles[i].set != HandleSet_Used)
@ -1141,16 +1153,16 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|| !bresult)
{
rep("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", index, owner, type, "-1");
}
else
{
char buffer[32];
ke::SafeSprintf(buffer, sizeof(buffer), "%d", size);
rep("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", index, owner, type, buffer);
total_size += size;
}
}
rep("-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
rep(fn, "-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
}

View File

@ -35,7 +35,8 @@
#include <IHandleSys.h>
#include <stdio.h>
#include <sm_namehashset.h>
#include <am-string.h>
#include <amtl/am-string.h>
#include <amtl/am-function.h>
#include "common_logic.h"
#define HANDLESYS_MAX_HANDLES (1<<15)
@ -111,7 +112,7 @@ struct QHandleType
}
};
typedef void (HANDLE_REPORTER)(const char *str, ...);
typedef ke::Lambda<void(const char *)> HandleReporter;
class HandleSystem :
public IHandleSys
@ -163,7 +164,7 @@ public: //IHandleSystem
const HandleAccess *pAccess,
HandleError *err);
void Dump(HANDLE_REPORTER rep);
void Dump(const HandleReporter &reporter);
/* Bypasses security checks. */
Handle_t FastCloneHandle(Handle_t hndl);

View File

@ -27,10 +27,15 @@
#include "RootConsoleMenu.h"
#include <amtl/am-string.h>
#include <sourcemod_version.h>
#include <ISourceMod.h>
#include <bridge/include/CoreProvider.h>
#include "HandleSys.h"
RootConsoleMenu g_RootMenu;
// Some top-level commands that are just thrown in here.
static bool sm_dump_handles(int client, const ICommandArgs *args);
RootConsoleMenu::RootConsoleMenu()
{
}
@ -49,6 +54,9 @@ void RootConsoleMenu::OnSourceModStartup(bool late)
{
AddRootConsoleCommand3("version", "Display version information", this);
AddRootConsoleCommand3("credits", "Display credits listing", this);
bridge->DefineCommand("sm_dump_handles", "Dumps Handle usage to a file for finding Handle leaks",
sm_dump_handles);
}
void RootConsoleMenu::OnSourceModAllInitialized()
@ -232,3 +240,45 @@ void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const ICommandAr
ConsolePrint(" http://www.sourcemod.net/");
}
}
static bool sm_dump_handles(int client, const ICommandArgs *args)
{
if (args->ArgC() < 2) {
bridge->ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
return true;
}
if (strcmp(args->Arg(1), "log") == 0) {
auto write_handles_to_game = [] (const char *str) -> void
{
char buffer[1024];
size_t len = ke::SafeSprintf(buffer, sizeof(buffer)-2, "%s", str);
buffer[len] = '\n';
buffer[len+1] = '\0';
bridge->LogToGame(buffer);
};
g_HandleSys.Dump(write_handles_to_game);
return true;
}
FILE *fp = nullptr;
auto write_handles_to_log = [&fp] (const char *str) -> void
{
fprintf(fp, "%s\n", str);
};
char filename[PLATFORM_MAX_PATH];
const char *arg = args->Arg(1);
g_pSM->BuildPath(Path_Game, filename, sizeof(filename), "%s", arg);
fp = fopen(filename, "wt");
if (!fp) {
bridge->ConsolePrint("Failed to open \"%s\" for writing", filename);
return true;
}
g_HandleSys.Dump(write_handles_to_log);
fclose(fp);
}

View File

@ -109,11 +109,6 @@ static void AddNatives(sp_nativeinfo_t *natives)
g_CoreNatives.AddNatives(natives);
}
static void DumpHandles(void (*dumpfn)(const char *fmt, ...))
{
g_HandleSys.Dump(dumpfn);
}
static void RegisterProfiler(IProfilingTool *tool)
{
g_ProfileToolManager.RegisterTool(tool);
@ -154,7 +149,6 @@ static sm_logic_t logic =
&g_DbgReporter,
GenerateError,
AddNatives,
DumpHandles,
RegisterProfiler,
OnRootCommand,
CDataPack::New,

View File

@ -70,67 +70,3 @@ CON_COMMAND(sm, "SourceMod Menu")
logicore.OnRootCommand(&cargs);
}
FILE *g_pHndlLog = NULL;
void write_handles_to_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(g_pHndlLog, fmt, ap);
fprintf(g_pHndlLog, "\n");
va_end(ap);
}
void write_handles_to_game(const char *fmt, ...)
{
size_t len;
va_list ap;
char buffer[1024];
va_start(ap, fmt);
len = ke::SafeSprintf(buffer, sizeof(buffer)-2, fmt, ap);
va_end(ap);
buffer[len] = '\n';
buffer[len+1] = '\0';
engine->LogPrint(buffer);
}
CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
{
#if SOURCE_ENGINE <= SE_DARKMESSIAH
CCommand args;
#endif
if (args.ArgC() < 2)
{
UTIL_ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
return;
}
if (strcmp(args.Arg(1), "log") != 0)
{
char filename[PLATFORM_MAX_PATH];
const char *arg = args.Arg(1);
g_SourceMod.BuildPath(Path_Game, filename, sizeof(filename), "%s", arg);
FILE *fp = fopen(filename, "wt");
if (!fp)
{
UTIL_ConsolePrint("Failed to open \"%s\" for writing", filename);
return;
}
g_pHndlLog = fp;
logicore.DumpHandles(write_handles_to_log);
g_pHndlLog = NULL;
fclose(fp);
}
else
{
logicore.DumpHandles(write_handles_to_game);
}
}

@ -1 +1 @@
Subproject commit c4c2aa3e97157407c3832b40fed43ba9cd24a2c1
Subproject commit 298217cbbfac16851bb58574bc6744f58b260b15