Alexandre Julliard : ntdll: Don' t call vectored exception handlers under the critical section.
Alexandre Julliard
julliard at winehq.org
Thu Dec 2 16:30:53 CST 2010
Module: wine
Branch: stable
Commit: ac8680b2ad320f9904b6f72736165697f312fe09
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ac8680b2ad320f9904b6f72736165697f312fe09
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Nov 10 20:55:07 2010 +0100
ntdll: Don't call vectored exception handlers under the critical section.
(cherry picked from commit 11e71ede147491381bba4762163803f540c7eb5b)
---
dlls/ntdll/exception.c | 25 ++++++++++++++++++++++---
1 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 63fd281..33868c7 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -44,6 +44,7 @@ typedef struct
{
struct list entry;
PVECTORED_EXCEPTION_HANDLER func;
+ ULONG count;
} VECTORED_HANDLER;
static struct list vectored_handlers = LIST_INIT(vectored_handlers);
@@ -158,21 +159,37 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
struct list *ptr;
LONG ret = EXCEPTION_CONTINUE_SEARCH;
EXCEPTION_POINTERS except_ptrs;
+ VECTORED_HANDLER *handler, *to_free = NULL;
except_ptrs.ExceptionRecord = rec;
except_ptrs.ContextRecord = context;
RtlEnterCriticalSection( &vectored_handlers_section );
- LIST_FOR_EACH( ptr, &vectored_handlers )
+ ptr = list_head( &vectored_handlers );
+ while (ptr)
{
- VECTORED_HANDLER *handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
+ handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
+ handler->count++;
+ RtlLeaveCriticalSection( &vectored_handlers_section );
+ RtlFreeHeap( GetProcessHeap(), 0, to_free );
+ to_free = NULL;
+
TRACE( "calling handler at %p code=%x flags=%x\n",
handler->func, rec->ExceptionCode, rec->ExceptionFlags );
ret = handler->func( &except_ptrs );
TRACE( "handler at %p returned %x\n", handler->func, ret );
+
+ RtlEnterCriticalSection( &vectored_handlers_section );
+ ptr = list_next( &vectored_handlers, ptr );
+ if (!--handler->count) /* removed during execution */
+ {
+ list_remove( &handler->entry );
+ to_free = handler;
+ }
if (ret == EXCEPTION_CONTINUE_EXECUTION) break;
}
RtlLeaveCriticalSection( &vectored_handlers_section );
+ RtlFreeHeap( GetProcessHeap(), 0, to_free );
return ret;
}
@@ -214,6 +231,7 @@ PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HA
if (handler)
{
handler->func = func;
+ handler->count = 1;
RtlEnterCriticalSection( &vectored_handlers_section );
if (first) list_add_head( &vectored_handlers, &handler->entry );
else list_add_tail( &vectored_handlers, &handler->entry );
@@ -237,7 +255,8 @@ ULONG WINAPI RtlRemoveVectoredExceptionHandler( PVOID handler )
VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
if (curr_handler == handler)
{
- list_remove( ptr );
+ if (!--curr_handler->count) list_remove( ptr );
+ else handler = NULL; /* don't free it yet */
ret = TRUE;
break;
}
More information about the wine-cvs
mailing list