ntdll: Don't call vectored exception handlers under the critical section.

This commit is contained in:
Alexandre Julliard 2010-11-10 20:55:07 +01:00
parent 177a7e5683
commit 11e71ede14
1 changed files with 22 additions and 3 deletions

View File

@ -44,6 +44,7 @@ typedef struct
{ {
struct list entry; struct list entry;
PVECTORED_EXCEPTION_HANDLER func; PVECTORED_EXCEPTION_HANDLER func;
ULONG count;
} VECTORED_HANDLER; } VECTORED_HANDLER;
static struct list vectored_handlers = LIST_INIT(vectored_handlers); 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; struct list *ptr;
LONG ret = EXCEPTION_CONTINUE_SEARCH; LONG ret = EXCEPTION_CONTINUE_SEARCH;
EXCEPTION_POINTERS except_ptrs; EXCEPTION_POINTERS except_ptrs;
VECTORED_HANDLER *handler, *to_free = NULL;
except_ptrs.ExceptionRecord = rec; except_ptrs.ExceptionRecord = rec;
except_ptrs.ContextRecord = context; except_ptrs.ContextRecord = context;
RtlEnterCriticalSection( &vectored_handlers_section ); 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", TRACE( "calling handler at %p code=%x flags=%x\n",
handler->func, rec->ExceptionCode, rec->ExceptionFlags ); handler->func, rec->ExceptionCode, rec->ExceptionFlags );
ret = handler->func( &except_ptrs ); ret = handler->func( &except_ptrs );
TRACE( "handler at %p returned %x\n", handler->func, ret ); 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; if (ret == EXCEPTION_CONTINUE_EXECUTION) break;
} }
RtlLeaveCriticalSection( &vectored_handlers_section ); RtlLeaveCriticalSection( &vectored_handlers_section );
RtlFreeHeap( GetProcessHeap(), 0, to_free );
return ret; return ret;
} }
@ -214,6 +231,7 @@ PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HA
if (handler) if (handler)
{ {
handler->func = func; handler->func = func;
handler->count = 1;
RtlEnterCriticalSection( &vectored_handlers_section ); RtlEnterCriticalSection( &vectored_handlers_section );
if (first) list_add_head( &vectored_handlers, &handler->entry ); if (first) list_add_head( &vectored_handlers, &handler->entry );
else list_add_tail( &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 ); VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
if (curr_handler == handler) if (curr_handler == handler)
{ {
list_remove( ptr ); if (!--curr_handler->count) list_remove( ptr );
else handler = NULL; /* don't free it yet */
ret = TRUE; ret = TRUE;
break; break;
} }