Make vectored exceptions thread-safe

svn path=/trunk/; revision=40787
This commit is contained in:
Thomas Bluemel 2009-05-04 18:06:15 +00:00
parent 007909b14a
commit 2e9b52a3a5

View file

@ -15,11 +15,14 @@
static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock; static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock;
static LIST_ENTRY RtlpVectoredExceptionHead; static LIST_ENTRY RtlpVectoredExceptionHead;
static volatile LONG RtlpVectoredExceptionsInstalled;
typedef struct _RTL_VECTORED_EXCEPTION_HANDLER typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
PVECTORED_EXCEPTION_HANDLER VectoredHandler; PVECTORED_EXCEPTION_HANDLER VectoredHandler;
ULONG Refs;
BOOLEAN Deleted;
} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER; } RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
@ -30,37 +33,70 @@ RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context) IN PCONTEXT Context)
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PRTL_VECTORED_EXCEPTION_HANDLER veh; PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
PVECTORED_EXCEPTION_HANDLER VectoredHandler; PVECTORED_EXCEPTION_HANDLER VectoredHandler;
EXCEPTION_POINTERS ExceptionInfo; EXCEPTION_POINTERS ExceptionInfo;
BOOLEAN Remove = FALSE;
BOOLEAN Ret = FALSE;
ExceptionInfo.ExceptionRecord = ExceptionRecord; ExceptionInfo.ExceptionRecord = ExceptionRecord;
ExceptionInfo.ContextRecord = Context; ExceptionInfo.ContextRecord = Context;
if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead) if(RtlpVectoredExceptionsInstalled)
{ {
RtlEnterCriticalSection(&RtlpVectoredExceptionLock); RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
for(CurrentEntry = RtlpVectoredExceptionHead.Flink; CurrentEntry = RtlpVectoredExceptionHead.Flink;
CurrentEntry != &RtlpVectoredExceptionHead; while (CurrentEntry != &RtlpVectoredExceptionHead)
CurrentEntry = CurrentEntry->Flink)
{ {
veh = CONTAINING_RECORD(CurrentEntry, veh = CONTAINING_RECORD(CurrentEntry,
RTL_VECTORED_EXCEPTION_HANDLER, RTL_VECTORED_EXCEPTION_HANDLER,
ListEntry); ListEntry);
VectoredHandler = RtlDecodePointer(veh->VectoredHandler); veh->Refs++;
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
VectoredHandler = RtlDecodePointer(veh->VectoredHandler);
if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION) if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
{ {
return TRUE; RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
if (--veh->Refs == 0)
{
RemoveEntryList (&veh->ListEntry);
InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
Remove = TRUE;
}
Ret = TRUE;
break;
} }
RtlEnterCriticalSection(&RtlpVectoredExceptionLock); RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
if (--veh->Refs == 0)
{
CurrentEntry = veh->ListEntry.Flink;
RemoveEntryList (&veh->ListEntry);
InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
RtlFreeHeap(RtlGetProcessHeap(),
0,
veh);
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
}
else
CurrentEntry = CurrentEntry->Flink;
} }
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
} }
return FALSE; if (Remove)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
veh);
}
return Ret;
} }
VOID VOID
@ -68,6 +104,7 @@ RtlpInitializeVectoredExceptionHandling(VOID)
{ {
InitializeListHead(&RtlpVectoredExceptionHead); InitializeListHead(&RtlpVectoredExceptionHead);
RtlInitializeCriticalSection(&RtlpVectoredExceptionLock); RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);
RtlpVectoredExceptionsInstalled = 0;
} }
@ -86,6 +123,8 @@ RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
if(veh != NULL) if(veh != NULL)
{ {
veh->VectoredHandler = RtlEncodePointer(VectoredHandler); veh->VectoredHandler = RtlEncodePointer(VectoredHandler);
veh->Refs = 1;
veh->Deleted = FALSE;
RtlEnterCriticalSection(&RtlpVectoredExceptionLock); RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
if(FirstHandler != 0) if(FirstHandler != 0)
{ {
@ -97,6 +136,7 @@ RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
InsertTailList(&RtlpVectoredExceptionHead, InsertTailList(&RtlpVectoredExceptionHead,
&veh->ListEntry); &veh->ListEntry);
} }
InterlockedIncrement (&RtlpVectoredExceptionsInstalled);
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
} }
@ -112,7 +152,8 @@ RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL; PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
ULONG Removed = FALSE; BOOLEAN Remove = FALSE;
ULONG Ret = FALSE;
RtlEnterCriticalSection(&RtlpVectoredExceptionLock); RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
for(CurrentEntry = RtlpVectoredExceptionHead.Flink; for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
@ -124,21 +165,29 @@ RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
ListEntry); ListEntry);
if(veh == VectoredHandlerHandle) if(veh == VectoredHandlerHandle)
{ {
RemoveEntryList(&veh->ListEntry); if (!veh->Deleted)
Removed = TRUE; {
break; if (--veh->Refs == 0)
{
RemoveEntryList (&veh->ListEntry);
Remove = TRUE;
}
veh->Deleted = TRUE;
Ret = TRUE;
break;
}
} }
} }
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
if(Removed) if(Remove)
{ {
RtlFreeHeap(RtlGetProcessHeap(), RtlFreeHeap(RtlGetProcessHeap(),
0, 0,
veh); veh);
} }
return Removed; return Ret;
} }
/* EOF */ /* EOF */