Since test errors reported in MR!1823, I gave a spin at scheding some light on these errors.
This series shall fix a couple of them, even there are still a couple standing (eg. https://testbot.winehq.org/JobDetails.pl?Key=127712).
From: Eric Pouech eric.pouech@gmail.com
Investigating the test failures in MR!1823, it turns out that sometimes in Win7, at process exit, not all the dll unload debug events are sent (in traces, only the last loaded dll gets the event). I don't know what it only shows now :-(, but that seems very replicable (it happens every time with new job to TestBot).
So mark the case of missing unload dll debug event as broken (still checking that the load dll debug event has been received).
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/kernel32/tests/debugger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 1dc5bd5fb46..7d4fbb6c7c0 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -1014,7 +1014,8 @@ static void test_debug_loop(int argc, char **argv) if (!ret) break; }
- ok( ole32_mod == (HMODULE)1, "ole32.dll was not reported\n" ); + /* sometimes not all unload events are sent on win7 */ + ok( ole32_mod == (HMODULE)1 || broken( ole32_mod != NULL ), "ole32.dll was not reported\n" ); ok( oleaut32_mod == (HMODULE)1, "oleaut32.dll was not reported\n" ); #ifdef _WIN64 ok( oleacc_mod == (HMODULE)1, "oleacc.dll was not reported\n" );
From: Eric Pouech eric.pouech@gmail.com
Even if there's a synchronisation mechanism between kernel32:debugger and its children which ensures that child has finished writing to and closed the blackbox logging file before reading it, there's no guarantee that the file is not re-opened by another process: antivirus, file indexing... And according to [1], even the OS itself can still have opened references to it.
So, always open/read the blackbox file in read share mode to work around this issue.
Also, harden the code for potential errors, and be nicer in where failures come from.
[1] https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/irp-mj-cleanu...
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53456
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/kernel32/tests/debugger.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 7d4fbb6c7c0..52cc965f013 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -132,38 +132,45 @@ static void save_blackbox(const char* logfile, void* blackbox, int size, const c { HANDLE hFile; DWORD written; + BOOL ret;
- hFile=CreateFileA(logfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + hFile = CreateFileA(logfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create %s: %lu\n", logfile, GetLastError()); if (hFile == INVALID_HANDLE_VALUE) return; - WriteFile(hFile, blackbox, size, &written, NULL); + ret = WriteFile(hFile, blackbox, size, &written, NULL); + ok(ret && written == size, "Error writing\n"); if (dbgtrace && dbgtrace[0]) - WriteFile(hFile, dbgtrace, strlen(dbgtrace), &written, NULL); + { + ret = WriteFile(hFile, dbgtrace, strlen(dbgtrace), &written, NULL); + ok(ret && written == strlen(dbgtrace), "Error writing\n"); + } CloseHandle(hFile); }
-static int load_blackbox(const char* logfile, void* blackbox, int size) +#define load_blackbox(a, b, c) _load_blackbox(__LINE__, (a), (b), (c)) +static int _load_blackbox(unsigned int line, const char* logfile, void* blackbox, int size) { HANDLE hFile; DWORD read; BOOL ret; char buf[4096];
- hFile=CreateFileA(logfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); + hFile = CreateFileA(logfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (hFile == INVALID_HANDLE_VALUE) { - ok(0, "unable to open '%s'\n", logfile); + ok_(__FILE__, line)(0, "unable to open '%s': %#lx\n", logfile, GetLastError()); return 0; } SetLastError(0xdeadbeef); - ret=ReadFile(hFile, blackbox, size, &read, NULL); + ret = ReadFile(hFile, blackbox, size, &read, NULL); ok(ret, "ReadFile failed: %ld\n", GetLastError()); ok(read == size, "wrong size for '%s': read=%ld\n", logfile, read); ret = ReadFile(hFile, buf, sizeof(buf) - 1, &read, NULL); if (ret && read) { buf[read] = 0; - trace("debugger traces:\n%s", buf); + trace("debugger traces:>>>\n%s\n<<< Done.\n", buf); } CloseHandle(hFile); return 1;
From: Eric Pouech eric.pouech@gmail.com
Win10 and Win11 can have some variations in debug events order (linked to when thread start debug event are generated).
https://bugs.winehq.org/show_bug.cgi?id=54159
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/kernel32/tests/debugger.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 52cc965f013..a3f09abaa70 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -436,24 +436,30 @@ static void process_attach_events(struct debugger_context *ctx, BOOL pass_except ok(ctx->dll_cnt > 2, "dll_cnt = %d\n", ctx->dll_cnt);
/* a new thread is created and it executes DbgBreakPoint, which causes the exception */ - ok(ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode); + /* Win11 doesn't generate it at this point (Win <= 10 do) */ if (ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) { - DWORD last_thread = ctx->ev.dwThreadId; - next_event(ctx, WAIT_EVENT_TIMEOUT); + DWORD last_thread; + + /* sometimes (at least Win10) several thread creations are reported here */ + do + { + last_thread = ctx->ev.dwThreadId; + next_event(ctx, WAIT_EVENT_TIMEOUT); + } while (ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT); ok(ctx->ev.dwThreadId == last_thread, "unexpected thread\n"); - }
- ok(ctx->ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode); - ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n", - ctx->ev.u.Exception.ExceptionRecord.ExceptionCode); - ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress == pDbgBreakPoint, "ExceptionAddress != DbgBreakPoint\n"); + ok(ctx->ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode); + ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n", + ctx->ev.u.Exception.ExceptionRecord.ExceptionCode); + ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress == pDbgBreakPoint, "ExceptionAddress != DbgBreakPoint\n");
- if (pass_exception) - { - ret = ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); - ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError()); - ctx->ev.dwDebugEventCode = -1; + if (pass_exception) + { + ret = ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); + ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError()); + ctx->ev.dwDebugEventCode = -1; + } }
/* flush debug events */