much improved reporting on gdi handle leaks ( you must completely run out of handles tho - which is rare now that quotas are implemented )

svn path=/trunk/; revision=12217
This commit is contained in:
Royce Mitchell III 2004-12-19 05:03:29 +00:00
parent 4a371112ec
commit b27cf5b226

View file

@ -19,7 +19,7 @@
/* /*
* GDIOBJ.C - GDI object manipulation routines * GDIOBJ.C - GDI object manipulation routines
* *
* $Id: gdiobj.c,v 1.80 2004/12/19 00:03:56 royce Exp $ * $Id: gdiobj.c,v 1.81 2004/12/19 05:03:29 royce Exp $
*/ */
#include <w32k.h> #include <w32k.h>
@ -212,33 +212,55 @@ GetObjectSize(DWORD ObjectType)
#ifdef DBG #ifdef DBG
static int leak_reported = 0; static int leak_reported = 0;
#define GDI_STACK_LEVELS 4 #define GDI_STACK_LEVELS 12
static ULONG GDIHandleAllocator[GDI_STACK_LEVELS][GDI_HANDLE_COUNT]; static ULONG GDIHandleAllocator[GDI_HANDLE_COUNT][GDI_STACK_LEVELS];
struct DbgOpenGDIHandle struct DbgOpenGDIHandle
{ {
ULONG loc; ULONG idx;
int count; int count;
}; };
#define H 1024 #define H 1024
static struct DbgOpenGDIHandle h[H]; static struct DbgOpenGDIHandle h[H];
void IntDumpHandleTable ( int which ) void IntDumpHandleTable()
{ {
int i, n = 0, j; int i, n = 0, j, k, J;
if ( leak_reported )
{
DPRINT1("gdi handle abusers already reported!\n");
return;
}
leak_reported = 1;
DPRINT1("reporting gdi handle abusers:\n");
/* step through GDI handle table and find out who our culprit is... */ /* step through GDI handle table and find out who our culprit is... */
for ( i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++ ) for ( i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++ )
{ {
for ( j = 0; j < n; j++ ) for ( j = 0; j < n; j++ )
{ {
if ( GDIHandleAllocator[which][i] == h[j].loc ) next:
break; J = h[j].idx;
for ( k = 0; k < GDI_STACK_LEVELS; k++ )
{
if ( GDIHandleAllocator[i][k]
!= GDIHandleAllocator[J][k] )
{
if ( ++j == n )
goto done;
else
goto next;
} }
}
goto done;
}
done:
if ( j < H ) if ( j < H )
{ {
if ( j == n ) if ( j == n )
{ {
h[j].loc = GDIHandleAllocator[which][i]; h[j].idx = i;
h[j].count = 1; h[j].count = 1;
n = n + 1; n = n + 1;
} }
@ -252,25 +274,30 @@ void IntDumpHandleTable ( int which )
if ( h[i].count < h[i+1].count ) if ( h[i].count < h[i+1].count )
{ {
struct DbgOpenGDIHandle t; struct DbgOpenGDIHandle t;
t.loc = h[i+1].loc; t = h[i+1];
t.count = h[i+1].count; h[i+1] = h[i];
h[i+1].loc = h[i].loc;
h[i+1].count = h[i].count;
j = i; j = i;
while ( j > 0 && h[j-1].count < t.count ) while ( j > 0 && h[j-1].count < t.count )
j--; j--;
h[j] = t; h[j] = t;
} }
} }
/* print the first 30 offenders... */ /* print the worst offenders... */
DbgPrint ( "Worst GDI Handle leak offenders - stack trace level %i (out of %i unique locations):\n", which, n ); DbgPrint ( "Worst GDI Handle leak offenders (out of %i unique locations):\n", n );
for ( i = 0; i < 30 && i < n; i++ ) for ( i = 0; i < n && h[i].count > 1; i++ )
{ {
DbgPrint ( "\t" ); int j;
if ( !KeRosPrintAddress ( (PVOID)h[i].loc ) ) DbgPrint ( " %i allocs: ", h[i].count );
DbgPrint ( "<%X>", h[i].loc ); for ( j = 0; j < GDI_STACK_LEVELS; j++ )
DbgPrint ( " (%i allocations)\n", h[i].count ); {
ULONG Addr = GDIHandleAllocator[h[i].idx][j];
if ( !KeRosPrintAddress ( (PVOID)Addr ) )
DbgPrint ( "<%X>", Addr );
} }
DbgPrint ( "\n" );
}
if ( i < n && h[i].count == 1 )
DbgPrint ( "(list terminated - the remaining entries have 1 allocation only)\n" );
} }
#endif /* DBG */ #endif /* DBG */
@ -377,14 +404,13 @@ LockHandle:
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
__asm mov [Frame], ebp __asm mov [Frame], ebp
#endif #endif
Frame = (PULONG)Frame[0]; /* step out of AllocObj() */
for ( which = 0; which < GDI_STACK_LEVELS && Frame[1] != 0 && Frame[1] != 0xDEADBEEF; which++ ) for ( which = 0; which < GDI_STACK_LEVELS && Frame[1] != 0 && Frame[1] != 0xDEADBEEF; which++ )
{ {
GDIHandleAllocator[which][Index] = Frame[1]; /* step out of AllocObj() */ GDIHandleAllocator[Index][which] = Frame[1];
Frame = ((PULONG)Frame[0]); Frame = ((PULONG)Frame[0]);
} }
for ( ; which < GDI_STACK_LEVELS; which++ ) for ( ; which < GDI_STACK_LEVELS; which++ )
GDIHandleAllocator[which][Index] = 0xDEADBEEF; GDIHandleAllocator[Index][which] = 0xDEADBEEF;
} }
#endif /* DBG */ #endif /* DBG */
@ -416,18 +442,7 @@ LockHandle:
ExFreeToPagedLookasideList(LookasideList, newObject); ExFreeToPagedLookasideList(LookasideList, newObject);
DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n"); DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n");
#ifdef DBG #ifdef DBG
if ( !leak_reported ) IntDumpHandleTable();
{
DPRINT1("reporting gdi handle abusers:\n");
int which;
for ( which = 0; which < GDI_STACK_LEVELS; which++ )
IntDumpHandleTable(which);
leak_reported = 1;
}
else
{
DPRINT1("gdi handle abusers already reported!\n");
}
#endif /* DBG */ #endif /* DBG */
} }
else else