From: Paul Gofman pgofman@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57011 --- dlls/kernel32/tests/sync.c | 33 +++++++++++++++++++++++++++++++++ dlls/ntdll/sync.c | 5 ++++- 2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index c06ced47298..b26657b07fa 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -27,6 +27,7 @@ #include <windef.h> #include <winbase.h> #include <winternl.h> +#include <msvcrt/setjmp.h>
#include "wine/test.h"
@@ -2732,9 +2733,26 @@ static void test_apc_deadlock(void) CloseHandle(pi.hProcess); }
+static jmp_buf bad_cs_jmpbuf; + +static LONG WINAPI bad_cs_handler( EXCEPTION_POINTERS *eptr ) +{ + EXCEPTION_RECORD *rec = eptr->ExceptionRecord; + + ok(!rec->NumberParameters, "got %lu.\n", rec->NumberParameters); + ok(rec->ExceptionFlags == EXCEPTION_NONCONTINUABLE + || rec->ExceptionFlags == (EXCEPTION_NONCONTINUABLE | EXCEPTION_SOFTWARE_ORIGINATE), + "got %#lx.\n", rec->ExceptionFlags); + longjmp(bad_cs_jmpbuf, rec->ExceptionCode); + return EXCEPTION_CONTINUE_SEARCH; +} + static void test_crit_section(void) { + void *vectored_handler; CRITICAL_SECTION cs; + int exc_code; + HANDLE old; BOOL ret;
/* Win8+ does not initialize debug info, one has to use RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO @@ -2798,6 +2816,21 @@ static void test_crit_section(void)
DeleteCriticalSection(&cs); ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo); + + ret = pInitializeCriticalSectionEx(&cs, 0, 0); + ok(ret, "got error %lu.\n", GetLastError()); + old = cs.LockSemaphore; + cs.LockSemaphore = (HANDLE)0xdeadbeef; + + cs.LockCount = 0; + vectored_handler = AddVectoredExceptionHandler(TRUE, bad_cs_handler); + if (!(exc_code = setjmp(bad_cs_jmpbuf))) + EnterCriticalSection(&cs); + ok(cs.LockCount, "got %ld.\n", cs.LockCount); + ok(exc_code == STATUS_INVALID_HANDLE, "got %#x.\n", exc_code); + RemoveVectoredExceptionHandler(vectored_handler); + cs.LockSemaphore = old; + DeleteCriticalSection(&cs); }
static DWORD WINAPI thread_proc(LPVOID unused) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 139931a595e..522ce0a2142 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -313,6 +313,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS status = wait_semaphore( crit, timeout );
if (status == STATUS_WAIT_0) break; + if (status != WAIT_TIMEOUT) return status;
timeout = (TRACE_ON(relay) ? 300 : 60);
@@ -368,6 +369,8 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
if (InterlockedIncrement( &crit->LockCount )) { + NTSTATUS status; + if (crit->OwningThread == ULongToHandle(GetCurrentThreadId())) { crit->RecursionCount++; @@ -375,7 +378,7 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) }
/* Now wait for it */ - RtlpWaitForCriticalSection( crit ); + if ((status = RtlpWaitForCriticalSection( crit ))) RtlRaiseStatus( status ); } done: crit->OwningThread = ULongToHandle(GetCurrentThreadId());
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147433
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000001EE00D2, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
The bug suggests that it is a regression from 2745228b14d138ea2c7f631c212440ecf7b8f453 ("ntdll: Don't use debug info presence to detect critical section global status.") but essentially the program (and more so the user script it is executing) depends on semi-random stack data. Which effectively results into random CS passed to EnterCriticalSection() from msvcrt (and it doesn't look like msvcrt is doing anything wrong). But now when Wine decides it should treat LockSemaphore as a semaphore and that is not a waitable object it spins in a tight loop outputting an error, while Windows under the same conditions throws an exception from RtlEnterCriticalSection(). I am putting a bit more details on app and script behaviour into the bug ticket.
I didn't include direct call to RtlpWaitForCriticalSection() in test because it doesn't return the status on Windows like Wine does (it is probably just a void function, the return value looks semi-random and doesn't make sense). But I verified that it doesn't hang or crash under the same conditions. If we want to make this aspect better match Windows we could maybe call an internal helper from RtlEnterCriticalSection() instead of RtlpWaitForCriticalSection() but I judged that we probably don't need to touch it until something depends on that.