mirror of https://github.com/FWGS/xash3d-fwgs
engine: try to detect LoadLibrary/FreeLibrary leaks
This commit is contained in:
parent
8eec5389fe
commit
c395acad63
|
@ -330,7 +330,7 @@ static ref_api_t gEngfuncs =
|
||||||
_Mem_Realloc,
|
_Mem_Realloc,
|
||||||
_Mem_Free,
|
_Mem_Free,
|
||||||
|
|
||||||
COM_LoadLibrary,
|
_COM_LoadLibrary,
|
||||||
COM_FreeLibrary,
|
COM_FreeLibrary,
|
||||||
COM_GetProcAddress,
|
COM_GetProcAddress,
|
||||||
|
|
||||||
|
|
|
@ -1197,6 +1197,8 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DLL_PrintLeaks( void );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Host_Shutdown
|
Host_Shutdown
|
||||||
|
@ -1225,6 +1227,8 @@ void EXPORT Host_Shutdown( void )
|
||||||
Host_FreeCommon();
|
Host_FreeCommon();
|
||||||
Platform_Shutdown();
|
Platform_Shutdown();
|
||||||
|
|
||||||
|
DLL_PrintLeaks();
|
||||||
|
|
||||||
// must be last, console uses this
|
// must be last, console uses this
|
||||||
Mem_FreePool( &host.mempool );
|
Mem_FreePool( &host.mempool );
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,11 @@ typedef struct dll_user_s
|
||||||
} dll_user_t;
|
} dll_user_t;
|
||||||
|
|
||||||
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath );
|
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath );
|
||||||
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath );
|
|
||||||
|
#define COM_LoadLibrary( dllname, build_ordinals_table, directpath ) \
|
||||||
|
_COM_LoadLibrary( dllname, build_ordinals_table, directpath, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
void *_COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath, const char *name, int line );
|
||||||
void *COM_GetProcAddress( void *hInstance, const char *name );
|
void *COM_GetProcAddress( void *hInstance, const char *name );
|
||||||
const char *COM_NameForFunction( void *hInstance, void *function );
|
const char *COM_NameForFunction( void *hInstance, void *function );
|
||||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName ); // Save/Restore version
|
void *COM_FunctionFromName_SR( void *hInstance, const char *pName ); // Save/Restore version
|
||||||
|
|
|
@ -24,6 +24,127 @@ GNU General Public License for more details.
|
||||||
#include "platform/emscripten/lib_em.h"
|
#include "platform/emscripten/lib_em.h"
|
||||||
#include "platform/apple/lib_ios.h"
|
#include "platform/apple/lib_ios.h"
|
||||||
|
|
||||||
|
#define ENABLE_REFCOUNT_CHECK
|
||||||
|
|
||||||
|
#ifdef ENABLE_REFCOUNT_CHECK
|
||||||
|
struct dll_t
|
||||||
|
{
|
||||||
|
void *hInstance;
|
||||||
|
char name[256];
|
||||||
|
char file[256];
|
||||||
|
int line;
|
||||||
|
|
||||||
|
int refcount;
|
||||||
|
struct dll_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dll_t *dlls = NULL;
|
||||||
|
|
||||||
|
void *DLL_FindInListAndIncrement( const char *name )
|
||||||
|
{
|
||||||
|
struct dll_t *dll;
|
||||||
|
|
||||||
|
for( dll = dlls; dll; dll = dll->next )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( name, dll->name ))
|
||||||
|
{
|
||||||
|
dll->refcount++;
|
||||||
|
return dll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DLL_AddToList( const char *name, void *hInstance, const char *file, int line )
|
||||||
|
{
|
||||||
|
struct dll_t *newdll;
|
||||||
|
|
||||||
|
if( !hInstance ) return NULL;
|
||||||
|
|
||||||
|
newdll = DLL_FindInListAndIncrement( name );
|
||||||
|
if( newdll )
|
||||||
|
return newdll;
|
||||||
|
|
||||||
|
newdll = Mem_Malloc( host.mempool, sizeof( *newdll ));
|
||||||
|
|
||||||
|
newdll->hInstance = hInstance;
|
||||||
|
Q_strncpy( newdll->name, name, sizeof( newdll->name ));
|
||||||
|
Q_strncpy( newdll->file, file, sizeof( newdll->file ));
|
||||||
|
newdll->line = line;
|
||||||
|
newdll->refcount = 1;
|
||||||
|
newdll->next = dlls;
|
||||||
|
|
||||||
|
dlls = newdll;
|
||||||
|
|
||||||
|
return newdll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DLL_Free( void *_dll )
|
||||||
|
{
|
||||||
|
struct dll_t *dll = _dll;
|
||||||
|
void *hinst = dll->hInstance;
|
||||||
|
|
||||||
|
dll->refcount--;
|
||||||
|
|
||||||
|
if( dll->refcount == 0 )
|
||||||
|
{
|
||||||
|
struct dll_t **back, *find;
|
||||||
|
|
||||||
|
back = &dlls;
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
find = *back;
|
||||||
|
if( !find ) break;
|
||||||
|
|
||||||
|
if( find == dll )
|
||||||
|
{
|
||||||
|
*back = dll->next;
|
||||||
|
|
||||||
|
Mem_Free( dll );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
back = &find->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hinst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DLL_GetInstance( void *_dll )
|
||||||
|
{
|
||||||
|
struct dll_t *dll = _dll;
|
||||||
|
|
||||||
|
return dll->hInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DLL_PrintLeaks( void )
|
||||||
|
{
|
||||||
|
struct dll_t *dll;
|
||||||
|
|
||||||
|
for( dll = dlls; dll; dll = dll->next )
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "UNLOADED LIBRARY DETECTED: %s loaded at %s:%i!\n", dll->name, dll->file, dll->line );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void *DLL_AddToList( const char *name, void *hInstance, const char *file, int line )
|
||||||
|
{
|
||||||
|
return hInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DLL_Free( void *_dll )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DLL_GetInstance( void *_dll )
|
||||||
|
{
|
||||||
|
return _dll;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef XASH_DLL_LOADER // wine-based dll loader
|
#ifdef XASH_DLL_LOADER // wine-based dll loader
|
||||||
void * Loader_LoadLibrary (const char *name);
|
void * Loader_LoadLibrary (const char *name);
|
||||||
void * Loader_GetProcAddress (void *hndl, const char *name);
|
void * Loader_GetProcAddress (void *hndl, const char *name);
|
||||||
|
@ -33,7 +154,6 @@ const char * Loader_GetFuncName( void *hndl, void *func);
|
||||||
const char * Loader_GetFuncName_int( void *wm , void *func);
|
const char * Loader_GetFuncName_int( void *wm , void *func);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef XASH_NO_LIBDL
|
#ifdef XASH_NO_LIBDL
|
||||||
#ifndef XASH_DLL_LOADER
|
#ifndef XASH_DLL_LOADER
|
||||||
#error Enable at least one dll backend!!!
|
#error Enable at least one dll backend!!!
|
||||||
|
@ -74,7 +194,7 @@ qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath )
|
void *_COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath, const char *file, int line )
|
||||||
{
|
{
|
||||||
dll_user_t *hInst = NULL;
|
dll_user_t *hInst = NULL;
|
||||||
void *pHandle = NULL;
|
void *pHandle = NULL;
|
||||||
|
@ -95,7 +215,7 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
|
||||||
#ifdef XASH_DLL_LOADER
|
#ifdef XASH_DLL_LOADER
|
||||||
if( host.enabledll && ( pHandle = Loader_LoadLibrary(dllname)) )
|
if( host.enabledll && ( pHandle = Loader_LoadLibrary(dllname)) )
|
||||||
{
|
{
|
||||||
return pHandle;
|
return DLL_AddToList( dllname, pHandle, file, line );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -104,7 +224,7 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
|
||||||
{
|
{
|
||||||
pHandle = dlopen( dllname, RTLD_LAZY );
|
pHandle = dlopen( dllname, RTLD_LAZY );
|
||||||
if( pHandle )
|
if( pHandle )
|
||||||
return pHandle;
|
return DLL_AddToList( dllname, pHandle, file, line );
|
||||||
|
|
||||||
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
||||||
COM_PushLibraryError( dlerror() );
|
COM_PushLibraryError( dlerror() );
|
||||||
|
@ -151,38 +271,42 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
|
||||||
|
|
||||||
Mem_Free( hInst );
|
Mem_Free( hInst );
|
||||||
|
|
||||||
return pHandle;
|
return DLL_AddToList( dllname, pHandle, file, line );
|
||||||
}
|
}
|
||||||
|
|
||||||
void COM_FreeLibrary( void *hInstance )
|
void COM_FreeLibrary( void *hInstance )
|
||||||
{
|
{
|
||||||
|
void *hinst = DLL_Free( hInstance );
|
||||||
|
|
||||||
#ifdef XASH_DLL_LOADER
|
#ifdef XASH_DLL_LOADER
|
||||||
void *wm;
|
void *wm;
|
||||||
if( host.enabledll && (wm = Loader_GetDllHandle( hInstance )) )
|
if( host.enabledll && (wm = Loader_GetDllHandle( hinst )) )
|
||||||
return Loader_FreeLibrary( hInstance );
|
return Loader_FreeLibrary( hinst );
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef Platform_POSIX_FreeLibrary
|
#ifdef Platform_POSIX_FreeLibrary
|
||||||
Platform_POSIX_FreeLibrary( hInstance );
|
Platform_POSIX_FreeLibrary( hinst );
|
||||||
#else
|
#else
|
||||||
dlclose( hInstance );
|
dlclose( hinst );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *COM_GetProcAddress( void *hInstance, const char *name )
|
void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||||
{
|
{
|
||||||
|
void *hinst = DLL_GetInstance( hInstance );
|
||||||
|
|
||||||
#ifdef XASH_DLL_LOADER
|
#ifdef XASH_DLL_LOADER
|
||||||
void *wm;
|
void *wm;
|
||||||
if( host.enabledll && (wm = Loader_GetDllHandle( hInstance )) )
|
if( host.enabledll && ( wm = Loader_GetDllHandle( hinst )))
|
||||||
return Loader_GetProcAddress(hInstance, name);
|
return Loader_GetProcAddress( hinst, name );
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if Platform_POSIX_GetProcAddress
|
#if Platform_POSIX_GetProcAddress
|
||||||
return Platform_POSIX_GetProcAddress( hInstance, name );
|
return Platform_POSIX_GetProcAddress( hinst, name );
|
||||||
#else
|
#else
|
||||||
return dlsym( hInstance, name );
|
return dlsym( hinst, name );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,9 +340,11 @@ static int d_dladdr( void *sym, Dl_info *info )
|
||||||
|
|
||||||
const char *COM_NameForFunction( void *hInstance, void *function )
|
const char *COM_NameForFunction( void *hInstance, void *function )
|
||||||
{
|
{
|
||||||
|
void *hinst = DLL_GetInstance( hInstance );
|
||||||
|
|
||||||
#ifdef XASH_DLL_LOADER
|
#ifdef XASH_DLL_LOADER
|
||||||
void *wm;
|
void *wm;
|
||||||
if( host.enabledll && (wm = Loader_GetDllHandle( hInstance )) )
|
if( host.enabledll && ( wm = Loader_GetDllHandle( hinst )))
|
||||||
#error ConvertMangledName
|
#error ConvertMangledName
|
||||||
return Loader_GetFuncName_int( wm, function );
|
return Loader_GetFuncName_int( wm, function );
|
||||||
else
|
else
|
||||||
|
|
|
@ -363,7 +363,7 @@ typedef struct ref_api_s
|
||||||
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
||||||
|
|
||||||
// library management
|
// library management
|
||||||
void *(*COM_LoadLibrary)( const char *name, int build_ordinals_table, qboolean directpath );
|
void *(*COM_LoadLibrary)( const char *name, int build_ordinals_table, qboolean directpath, const char *file, int line );
|
||||||
void (*COM_FreeLibrary)( void *handle );
|
void (*COM_FreeLibrary)( void *handle );
|
||||||
void *(*COM_GetProcAddress)( void *handle, const char *name );
|
void *(*COM_GetProcAddress)( void *handle, const char *name );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue