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

Alexandre Julliard julliard at winehq.org
Thu Nov 11 12:05:47 CST 2010


Module: wine
Branch: master
Commit: 11e71ede147491381bba4762163803f540c7eb5b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=11e71ede147491381bba4762163803f540c7eb5b

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.

---

 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