diff --git a/debugger/dbg.y b/debugger/dbg.y index e6f453dce45..96c6c7bb8e8 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -693,6 +693,9 @@ DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance case CONTROL_C_EXIT: fprintf( stderr, "^C" ); break; + case EXCEPTION_CRITICAL_SECTION_WAIT: + fprintf( stderr, "critical section %08lx wait failed", rec->ExceptionInformation[0] ); + break; default: fprintf( stderr, "%08lx", rec->ExceptionCode ); break; diff --git a/include/winbase.h b/include/winbase.h index 7a21b01695c..69a656faa8f 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -973,6 +973,8 @@ typedef DWORD (WINAPI *LPPROGRESS_ROUTINE)(LARGE_INTEGER, LARGE_INTEGER, LARGE_I #define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE #define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT +/* Wine extension; Windows doesn't have a name for this code */ +#define EXCEPTION_CRITICAL_SECTION_WAIT 0xc0000194 #define DUPLICATE_CLOSE_SOURCE 0x00000001 #define DUPLICATE_SAME_ACCESS 0x00000002 diff --git a/scheduler/critsection.c b/scheduler/critsection.c index 1f46cdbdc42..d6e666aa287 100644 --- a/scheduler/critsection.c +++ b/scheduler/critsection.c @@ -10,6 +10,7 @@ #include #include "winerror.h" #include "winbase.h" +#include "ntddk.h" #include "heap.h" #include "debugtools.h" #include "thread.h" @@ -78,21 +79,30 @@ void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit ) } /* Now wait for it */ - res = WaitForSingleObject( crit->LockSemaphore, 5000L ); - if ( res == WAIT_TIMEOUT ) + for (;;) { - ERR_(win32)("Critical section %p wait timed out, retrying (60 sec)\n", crit ); - res = WaitForSingleObject( crit->LockSemaphore, 60000L ); - } - if ( res == WAIT_TIMEOUT && TRACE_ON(relay) ) - { - ERR_(win32)("Critical section %p wait timed out, retrying (5 min)\n", crit ); - res = WaitForSingleObject( crit->LockSemaphore, 300000L ); - } - if (res != STATUS_WAIT_0) - { - ERR_(win32)("Critical section %p wait failed err=%lx\n", crit, res ); - /* FIXME: should raise an exception */ + EXCEPTION_RECORD rec; + + res = WaitForSingleObject( crit->LockSemaphore, 5000L ); + if ( res == WAIT_TIMEOUT ) + { + ERR_(win32)("Critical section %p wait timed out, retrying (60 sec)\n", crit ); + res = WaitForSingleObject( crit->LockSemaphore, 60000L ); + if ( res == WAIT_TIMEOUT && TRACE_ON(relay) ) + { + ERR_(win32)("Critical section %p wait timed out, retrying (5 min)\n", crit ); + res = WaitForSingleObject( crit->LockSemaphore, 300000L ); + } + } + if (res == STATUS_WAIT_0) break; + + rec.ExceptionCode = EXCEPTION_CRITICAL_SECTION_WAIT; + rec.ExceptionFlags = 0; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = RtlRaiseException; /* sic */ + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = (DWORD)crit; + RtlRaiseException( &rec ); } } crit->OwningThread = GetCurrentThreadId();