From 3171d4fb7bf48648a595e60c0f8ec02414b63806 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 25 Oct 2021 23:58:39 -0700 Subject: [PATCH] Bump handle limit to 1MB. This bumps the handle bits to 20 and reduces the serial/cookie bits to 12. A warning is emitted if a single owner creates more than 100k handles. Tested on mock srcds with sm_dump_handles. --- core/logic/HandleSys.cpp | 37 ++++++++++++++++++++++++++++++++----- core/logic/HandleSys.h | 11 +++++++---- core/logic/ShareSys.h | 8 +++++--- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/core/logic/HandleSys.cpp b/core/logic/HandleSys.cpp index 4fc753f6..c1c1b930 100644 --- a/core/logic/HandleSys.cpp +++ b/core/logic/HandleSys.cpp @@ -47,6 +47,8 @@ #include "sm_invalidparamhandler.h" #endif +using namespace std::string_literals; + HandleSystem g_HandleSys; QHandle *ignore_handle; @@ -299,6 +301,28 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, } } + if (owner) + { + owner->num_handles++; + if (!owner->warned_handle_usage && owner->num_handles >= HANDLESYS_WARN_USAGE) + { + owner->warned_handle_usage = true; + + std::string path = ""; + if (auto plugin = scripts->FindPluginByIdentity(owner)) + { + path = "plugin "s + plugin->GetFilename(); + } + else if (auto ext = g_Extensions.GetExtensionFromIdent(owner)) + { + path = "extension "s + ext->GetFilename(); + } + + logger->LogError("[SM] Warning: %s is using more than %d handles!", + path.c_str(), HANDLESYS_WARN_USAGE); + } + } + QHandle *pHandle = &m_Handles[handle]; assert(pHandle->set == false); @@ -320,7 +344,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, /* Create the hash value */ Handle_t hash = pHandle->serial; - hash <<= 16; + hash <<= HANDLESYS_HANDLE_BITS; hash |= handle; /* Add a reference count to the type */ @@ -484,7 +508,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle, unsigned int *in_index, bool ignoreFree) { - unsigned int serial = (handle >> 16); + unsigned int serial = (handle >> HANDLESYS_HANDLE_BITS); unsigned int index = (handle & HANDLESYS_HANDLE_MASK); if (index == 0 || index > m_HandleTail || index > HANDLESYS_MAX_HANDLES) @@ -640,7 +664,7 @@ Handle_t HandleSystem::FastCloneHandle(Handle_t hndl) void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index) { #ifndef NDEBUG - unsigned int serial = (hndl >> 16); + unsigned int serial = (hndl >> HANDLESYS_HANDLE_BITS); #endif index = (hndl & HANDLESYS_HANDLE_MASK); @@ -664,6 +688,9 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) QHandleType *pType = &m_Types[pHandle->type]; + if (pHandle->owner && pHandle->owner->num_handles > 0) + pHandle->owner->num_handles--; + if (pHandle->clone) { /* If we're a clone, decrease the parent reference count */ @@ -1138,12 +1165,12 @@ void HandleSystem::Dump(const HandleReporter &fn) continue; } /* Get the index */ - unsigned int index = (m_Handles[i].serial << 16) | i; + unsigned int index = (m_Handles[i].serial << HANDLESYS_HANDLE_BITS) | i; /* Determine the owner */ const char *owner = "UNKNOWN"; if (m_Handles[i].owner) { - IdentityToken_t *pOwner = m_Handles[i].owner; + IdentityToken_t *pOwner = m_Handles[i].owner; if (pOwner == g_pCoreIdent) { owner = "CORE"; diff --git a/core/logic/HandleSys.h b/core/logic/HandleSys.h index 99c9daa9..2fc786b8 100644 --- a/core/logic/HandleSys.h +++ b/core/logic/HandleSys.h @@ -42,14 +42,17 @@ #include #include "common_logic.h" -#define HANDLESYS_MAX_HANDLES (1<<15) +#define HANDLESYS_HANDLE_BITS 20 +#define HANDLESYS_MAX_HANDLES ((1 << HANDLESYS_HANDLE_BITS) - 1) #define HANDLESYS_MAX_TYPES (1<<9) #define HANDLESYS_MAX_SUBTYPES 0xF #define HANDLESYS_SUBTYPE_MASK 0xF #define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1)) -#define HANDLESYS_MAX_SERIALS 0xFFFF -#define HANDLESYS_SERIAL_MASK 0xFFFF0000 -#define HANDLESYS_HANDLE_MASK 0x0000FFFF +#define HANDLESYS_SERIAL_BITS (32 - HANDLESYS_HANDLE_BITS) +#define HANDLESYS_MAX_SERIALS (1 << HANDLESYS_SERIAL_BITS) +#define HANDLESYS_SERIAL_MASK (((1 << HANDLESYS_SERIAL_BITS) - 1) << HANDLESYS_HANDLE_BITS) +#define HANDLESYS_HANDLE_MASK ((1 << HANDLESYS_HANDLE_BITS) - 1) +#define HANDLESYS_WARN_USAGE 100000 #define HANDLESYS_MEMUSAGE_MIN_VERSION 3 diff --git a/core/logic/ShareSys.h b/core/logic/ShareSys.h index c6d1282c..20fc9579 100644 --- a/core/logic/ShareSys.h +++ b/core/logic/ShareSys.h @@ -49,9 +49,11 @@ namespace SourceMod { struct IdentityToken_t { - Handle_t ident; - void *ptr; - IdentityType_t type; + Handle_t ident = 0; + void *ptr = nullptr; + IdentityType_t type = 0; + size_t num_handles = 0; + bool warned_handle_usage = false; }; };