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.
This commit is contained in:
David Anderson 2021-10-25 23:58:39 -07:00 committed by Your Name
parent 066818fbec
commit 3171d4fb7b
3 changed files with 44 additions and 12 deletions

View File

@ -47,6 +47,8 @@
#include "sm_invalidparamhandler.h" #include "sm_invalidparamhandler.h"
#endif #endif
using namespace std::string_literals;
HandleSystem g_HandleSys; HandleSystem g_HandleSys;
QHandle *ignore_handle; 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 = "<unknown>";
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]; QHandle *pHandle = &m_Handles[handle];
assert(pHandle->set == false); assert(pHandle->set == false);
@ -320,7 +344,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
/* Create the hash value */ /* Create the hash value */
Handle_t hash = pHandle->serial; Handle_t hash = pHandle->serial;
hash <<= 16; hash <<= HANDLESYS_HANDLE_BITS;
hash |= handle; hash |= handle;
/* Add a reference count to the type */ /* Add a reference count to the type */
@ -484,7 +508,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
unsigned int *in_index, unsigned int *in_index,
bool ignoreFree) bool ignoreFree)
{ {
unsigned int serial = (handle >> 16); unsigned int serial = (handle >> HANDLESYS_HANDLE_BITS);
unsigned int index = (handle & HANDLESYS_HANDLE_MASK); unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
if (index == 0 || index > m_HandleTail || index > HANDLESYS_MAX_HANDLES) 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) void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index)
{ {
#ifndef NDEBUG #ifndef NDEBUG
unsigned int serial = (hndl >> 16); unsigned int serial = (hndl >> HANDLESYS_HANDLE_BITS);
#endif #endif
index = (hndl & HANDLESYS_HANDLE_MASK); index = (hndl & HANDLESYS_HANDLE_MASK);
@ -664,6 +688,9 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
QHandleType *pType = &m_Types[pHandle->type]; QHandleType *pType = &m_Types[pHandle->type];
if (pHandle->owner && pHandle->owner->num_handles > 0)
pHandle->owner->num_handles--;
if (pHandle->clone) if (pHandle->clone)
{ {
/* If we're a clone, decrease the parent reference count */ /* If we're a clone, decrease the parent reference count */
@ -1138,12 +1165,12 @@ void HandleSystem::Dump(const HandleReporter &fn)
continue; continue;
} }
/* Get the index */ /* 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 */ /* Determine the owner */
const char *owner = "UNKNOWN"; const char *owner = "UNKNOWN";
if (m_Handles[i].owner) if (m_Handles[i].owner)
{ {
IdentityToken_t *pOwner = m_Handles[i].owner; IdentityToken_t *pOwner = m_Handles[i].owner;
if (pOwner == g_pCoreIdent) if (pOwner == g_pCoreIdent)
{ {
owner = "CORE"; owner = "CORE";

View File

@ -42,14 +42,17 @@
#include <sm_namehashset.h> #include <sm_namehashset.h>
#include "common_logic.h" #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_TYPES (1<<9)
#define HANDLESYS_MAX_SUBTYPES 0xF #define HANDLESYS_MAX_SUBTYPES 0xF
#define HANDLESYS_SUBTYPE_MASK 0xF #define HANDLESYS_SUBTYPE_MASK 0xF
#define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1)) #define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
#define HANDLESYS_MAX_SERIALS 0xFFFF #define HANDLESYS_SERIAL_BITS (32 - HANDLESYS_HANDLE_BITS)
#define HANDLESYS_SERIAL_MASK 0xFFFF0000 #define HANDLESYS_MAX_SERIALS (1 << HANDLESYS_SERIAL_BITS)
#define HANDLESYS_HANDLE_MASK 0x0000FFFF #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 #define HANDLESYS_MEMUSAGE_MIN_VERSION 3

View File

@ -49,9 +49,11 @@ namespace SourceMod
{ {
struct IdentityToken_t struct IdentityToken_t
{ {
Handle_t ident; Handle_t ident = 0;
void *ptr; void *ptr = nullptr;
IdentityType_t type; IdentityType_t type = 0;
size_t num_handles = 0;
bool warned_handle_usage = false;
}; };
}; };