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:
		
							parent
							
								
									92ce0fe814
								
							
						
					
					
						commit
						cab60f7385
					
				| @ -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 = "<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]; | ||||
| 	 | ||||
| 	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"; | ||||
|  | ||||
| @ -42,14 +42,17 @@ | ||||
| #include <sm_namehashset.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_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 | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user