Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/debugger.c | 62 +++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index a2b5d1f410e..7fe4f872282 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -309,6 +309,56 @@ static void fetch_process_context(struct debugger_context *ctx) #define WAIT_EVENT_TIMEOUT 20000 #define POLL_EVENT_TIMEOUT 200
+#define test_reply_later(a) test_reply_later_(__LINE__,a) +static void test_reply_later_(unsigned int line, struct debugger_context *ctx) +{ + DEBUG_EVENT de0, de1; + HANDLE thread; + NTSTATUS status; + + if (!ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER)) + todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + else + { + ok_(__FILE__,line)(WaitForDebugEvent(&de0, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError()); + ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de0.dwDebugEventCode, + "delayed event differ, code:%x was:%x\n", de0.dwDebugEventCode, ctx->ev.dwDebugEventCode); + ok_(__FILE__,line)(ctx->ev.dwProcessId == de0.dwProcessId, + "delayed event differ, pid:%x was:%x\n", de0.dwProcessId, ctx->ev.dwProcessId); + ok_(__FILE__,line)(ctx->ev.dwThreadId == de0.dwThreadId, + "delayed event differ, tid:%x was:%x\n", de0.dwThreadId, ctx->ev.dwThreadId); + + if (ctx->ev.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != EXIT_THREAD_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) + { + thread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ctx->ev.dwThreadId); + ok_(__FILE__,line)(thread != INVALID_HANDLE_VALUE, "OpenThread failed, last error:%u\n", GetLastError()); + + status = NtSuspendThread(thread, NULL); + ok_(__FILE__,line)(!status, "NtSuspendThread failed, last error:%u\n", GetLastError()); + + ok_(__FILE__,line)(ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + + ok_(__FILE__,line)(!WaitForDebugEvent(&de1, 50), "WaitForDebugEvent succeeded.\n"); + status = NtResumeThread(thread, NULL); + + ok_(__FILE__,line)(!status, "NtResumeThread failed, last error:%u\n", GetLastError()); + CloseHandle(thread); + + ok_(__FILE__,line)(WaitForDebugEvent(&de1, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError()); + ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de1.dwDebugEventCode, + "delayed event differ, code:%x was:%x\n", de1.dwDebugEventCode, ctx->ev.dwDebugEventCode); + ok_(__FILE__,line)(ctx->ev.dwProcessId == de1.dwProcessId, + "delayed event differ, pid:%x was:%x\n", de1.dwProcessId, ctx->ev.dwProcessId); + ok_(__FILE__,line)(ctx->ev.dwThreadId == de1.dwThreadId, + "delayed event differ, tid:%x was:%x\n", de1.dwThreadId, ctx->ev.dwThreadId); + } + } +} + #define next_event(a,b) next_event_(__LINE__,a,b) static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout) { @@ -1273,7 +1323,11 @@ static void test_debugger(const char *argv0) next_event(&ctx, WAIT_EVENT_TIMEOUT); ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); wait_for_breakpoint(&ctx); - do next_event(&ctx, POLL_EVENT_TIMEOUT); + do + { + test_reply_later(&ctx); + next_event(&ctx, POLL_EVENT_TIMEOUT); + } while(ctx.ev.dwDebugEventCode != -1);
mem = VirtualAllocEx(pi.hProcess, NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -1297,6 +1351,7 @@ static void test_debugger(const char *argv0) debuggee_thread = get_debuggee_thread(&ctx, ctx.ev.dwThreadId);
wait_for_breakpoint(&ctx); + test_reply_later(&ctx); fetch_thread_context(debuggee_thread); ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == thread_proc, "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress); @@ -1304,8 +1359,11 @@ static void test_debugger(const char *argv0) get_ip(&debuggee_thread->ctx));
single_step(&ctx, debuggee_thread, thread_proc + 2); + test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc + 3); + test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc); + test_reply_later(&ctx);
byte = 0xc3; /* ret */ ret = WriteProcessMemory(pi.hProcess, thread_proc, &byte, 1, NULL); @@ -1328,6 +1386,7 @@ static void test_debugger(const char *argv0) ok(thread != NULL, "CreateRemoteThread failed: %u\n", GetLastError()); expect_event(&ctx, CREATE_THREAD_DEBUG_EVENT); expect_breakpoint_exception(&ctx, NULL); + test_reply_later(&ctx); expect_event(&ctx, EXIT_THREAD_DEBUG_EVENT);
/* BREAKPOINT_PROMPT */ @@ -1422,6 +1481,7 @@ static void test_debugger(const char *argv0)
do { + test_reply_later(&ctx); next_event(&ctx, WAIT_EVENT_TIMEOUT); ok (ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "got exception\n"); }
This flag causes the debug event to be replayed after the target thread continues. It can be used, after suspending the thread, to resume other threads and later return to the breaking.
This will help implementing gdb continue/step packets correctly.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Notes: This uses the same error handling logic in case of alloc_handle failure as for the user APC loop, the APC is considered as executed although it failed.
dlls/kernel32/tests/debugger.c | 2 +- server/debugger.c | 73 ++++++++++++++++++++++++++++++++-- server/object.h | 1 + server/thread.c | 3 +- 4 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 7fe4f872282..549de620ee5 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -317,7 +317,7 @@ static void test_reply_later_(unsigned int line, struct debugger_context *ctx) NTSTATUS status;
if (!ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER)) - todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); else { ok_(__FILE__,line)(WaitForDebugEvent(&de0, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError()); diff --git a/server/debugger.c b/server/debugger.c index 5b06b73b4be..5ff63b92b9c 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -38,7 +38,7 @@ #include "thread.h" #include "request.h"
-enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED }; +enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_DELAYED, EVENT_CONTINUED };
/* debug event */ struct debug_event @@ -265,6 +265,31 @@ static void link_event( struct debug_event *event ) } }
+/* resume a delayed debug event already in the queue */ +static void resume_event( struct debug_event *event ) +{ + struct debug_ctx *debug_ctx = event->debugger->debug_ctx; + + assert( debug_ctx ); + event->state = EVENT_QUEUED; + if (!event->sender->process->debug_event) + { + grab_object( debug_ctx ); + wake_up( &debug_ctx->obj, 0 ); + release_object( debug_ctx ); + } +} + +/* delay a debug event already in the queue to be replayed when thread wakes up */ +static void delay_event( struct debug_event *event ) +{ + struct debug_ctx *debug_ctx = event->debugger->debug_ctx; + + assert( debug_ctx ); + event->state = EVENT_DELAYED; + if (event->sender->process->debug_event == event) event->sender->process->debug_event = NULL; +} + /* find the next event that we can send to the debugger */ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx ) { @@ -273,6 +298,7 @@ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx ) LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { if (event->state == EVENT_SENT) continue; /* already sent */ + if (event->state == EVENT_DELAYED) continue; /* delayed until thread resumes */ if (event->sender->process->debug_event) continue; /* process busy with another one */ return event; } @@ -365,6 +391,29 @@ static int continue_debug_event( struct process *process, struct thread *thread, { struct debug_event *event;
+ if (status == DBG_REPLY_LATER) + { + /* if thread is suspended, delay all its events and resume process + * if not, reset the event for immediate replay */ + LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) + { + if (event->sender != thread) continue; + if (thread->suspend) + { + delay_event( event ); + resume_process( process ); + } + else if (event->state == EVENT_SENT) + { + assert( event->sender->process->debug_event == event ); + event->sender->process->debug_event = NULL; + resume_event( event ); + return 1; + } + } + return 1; + } + /* find the event in the queue */ LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { @@ -372,7 +421,6 @@ static int continue_debug_event( struct process *process, struct thread *thread, if (event->sender == thread) { assert( event->sender->process->debug_event == event ); - event->status = status; event->state = EVENT_CONTINUED; wake_up( &event->obj, 0 ); @@ -430,6 +478,24 @@ void generate_debug_event( struct thread *thread, int code, const void *arg ) } }
+void resume_delayed_debug_events( struct thread *thread ) +{ + struct thread *debugger = thread->process->debugger; + struct debug_event *event; + + if (debugger) + { + assert( debugger->debug_ctx ); + LIST_FOR_EACH_ENTRY( event, &debugger->debug_ctx->event_queue, struct debug_event, entry ) + { + if (event->sender != thread) continue; + if (event->state != EVENT_DELAYED) continue; + resume_event( event ); + suspend_process( thread->process ); + } + } +} + /* attach a process to a debugger thread and suspend it */ static int debugger_attach( struct process *process, struct thread *debugger ) { @@ -615,7 +681,8 @@ DECL_HANDLER(continue_debug_event) struct process *process;
if (req->status != DBG_EXCEPTION_NOT_HANDLED && - req->status != DBG_CONTINUE) + req->status != DBG_CONTINUE && + req->status != DBG_REPLY_LATER) { set_error( STATUS_INVALID_PARAMETER ); return; diff --git a/server/object.h b/server/object.h index 4a486e0d633..7f664ad2821 100644 --- a/server/object.h +++ b/server/object.h @@ -206,6 +206,7 @@ extern void sock_init(void);
extern int set_process_debugger( struct process *process, struct thread *debugger ); extern void generate_debug_event( struct thread *thread, int code, const void *arg ); +extern void resume_delayed_debug_events( struct thread *thread ); extern void generate_startup_debug_events( struct process *process, client_ptr_t entry ); extern void debug_exit_thread( struct thread *thread );
diff --git a/server/thread.c b/server/thread.c index edf70c61bde..6e677c8cf29 100644 --- a/server/thread.c +++ b/server/thread.c @@ -612,7 +612,8 @@ int resume_thread( struct thread *thread ) int old_count = thread->suspend; if (thread->suspend > 0) { - if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread ); + if (!(--thread->suspend)) resume_delayed_debug_events( thread ); + if (!(thread->suspend + thread->process->suspend)) wake_thread( thread ); } return old_count; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65553
Your paranoid android.
=== wxppro (32 bit report) ===
kernel32: debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt1.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:672: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt2.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt3.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt4.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt5.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt6.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:952: Test failed: CreateProcess failed, last error 0x2. debugger.c:957: Test failed: CheckRemoteDebuggerPresent failed, last error 0x57. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
=== w8adm (32 bit report) ===
kernel32: debugger.c:1456: Test failed: unexpected instruction pointer 003F0401
=== w1064v1809_ar (32 bit report) ===
kernel32: debugger.c:1456: Test failed: unexpected instruction pointer 771ED50E
=== w1064v1507 (64 bit report) ===
kernel32: debugger.c:1484: Test failed: delayed event differ, tid:d08 was:d14 debugger.c:1485: Test failed: ContinueDebugEvent failed, last error 87. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
=== w1064v1809 (64 bit report) ===
kernel32: debugger.c:1484: Test failed: delayed event differ, tid:1b94 was:1b84 debugger.c:1485: Test failed: ContinueDebugEvent failed, last error 87. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65552
Your paranoid android.
=== wxppro (32 bit report) ===
kernel32: debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt1.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:672: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt2.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt3.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt4.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt5.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:644: Test failed: CreateProcess: err=2 debugger.c:664: Test failed: Timed out waiting for the child to crash debugger.c:666: Test failed: GetExitCodeProcess failed: err=6 debugger.c:678: Test failed: wrong exit code : 7c90d96e debugger.c:699: Test failed: Timed out waiting for the debugger debugger.c:148: Test failed: wrong size for 'C:\DOCUME~1\winetest\LOCALS~1\Temp\wt6.tmp': read=0 debugger.c:703: Test failed: wrong debugger argument count: 2089871648 debugger.c:704: Test failed: the child and debugged pids don't match: 0 != 2089875048 debugger.c:707: Test failed: DebugSetProcessKillOnExit(FALSE) failed err=2089877688 debugger.c:709: Test failed: debugger reported 2089877569 failures debugger.c:952: Test failed: CreateProcess failed, last error 0x2. debugger.c:957: Test failed: CheckRemoteDebuggerPresent failed, last error 0x57. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
=== w1064v1809_he (32 bit report) ===
kernel32: debugger.c:142: Test failed: unable to open 'C:\Users\winetest\AppData\Local\Temp\wt9589.tmp' debugger.c:142: Test failed: failed to open: C:\Users\winetest\AppData\Local\Temp\wt9589.tmp debugger.c:704: Test failed: the child and debugged pids don't match: 3440 != 6808
=== w1064v1809_ja (32 bit report) ===
kernel32: debugger.c:142: Test failed: unable to open 'C:\Users\winetest\AppData\Local\Temp\wt3633.tmp' debugger.c:142: Test failed: failed to open: C:\Users\winetest\AppData\Local\Temp\wt3633.tmp debugger.c:704: Test failed: the child and debugged pids don't match: 6324 != 2580
=== w1064v1507 (64 bit report) ===
kernel32: debugger.c:1484: Test failed: delayed event differ, tid:d18 was:d68 debugger.c:1485: Test failed: ContinueDebugEvent failed, last error 87. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
=== w1064v1809 (64 bit report) ===
kernel32: debugger.c:1484: Test failed: delayed event differ, tid:1b80 was:1b40 debugger.c:1485: Test failed: ContinueDebugEvent failed, last error 87. debugger: Timeout
Report validation errors: kernel32:debugger has unaccounted for failure messages kernel32:debugger has unaccounted for skip messages The report seems to have been truncated
On 2/20/20 6:06 PM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
dlls/kernel32/tests/debugger.c | 62 +++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index a2b5d1f410e..7fe4f872282 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -309,6 +309,56 @@ static void fetch_process_context(struct debugger_context *ctx) #define WAIT_EVENT_TIMEOUT 20000 #define POLL_EVENT_TIMEOUT 200
+#define test_reply_later(a) test_reply_later_(__LINE__,a) +static void test_reply_later_(unsigned int line, struct debugger_context *ctx) +{
- DEBUG_EVENT de0, de1;
- HANDLE thread;
- NTSTATUS status;
- if (!ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER))
todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
- else
- {
ok_(__FILE__,line)(WaitForDebugEvent(&de0, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError());
ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de0.dwDebugEventCode,
"delayed event differ, code:%x was:%x\n", de0.dwDebugEventCode, ctx->ev.dwDebugEventCode);
ok_(__FILE__,line)(ctx->ev.dwProcessId == de0.dwProcessId,
"delayed event differ, pid:%x was:%x\n", de0.dwProcessId, ctx->ev.dwProcessId);
ok_(__FILE__,line)(ctx->ev.dwThreadId == de0.dwThreadId,
"delayed event differ, tid:%x was:%x\n", de0.dwThreadId, ctx->ev.dwThreadId);
if (ctx->ev.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT &&
ctx->ev.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT &&
ctx->ev.dwDebugEventCode != EXIT_THREAD_DEBUG_EVENT &&
ctx->ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT)
{
thread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ctx->ev.dwThreadId);
ok_(__FILE__,line)(thread != INVALID_HANDLE_VALUE, "OpenThread failed, last error:%u\n", GetLastError());
status = NtSuspendThread(thread, NULL);
ok_(__FILE__,line)(!status, "NtSuspendThread failed, last error:%u\n", GetLastError());
ok_(__FILE__,line)(ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER),
"ContinueDebugEvent failed, last error:%u\n", GetLastError());
ok_(__FILE__,line)(!WaitForDebugEvent(&de1, 50), "WaitForDebugEvent succeeded.\n");
status = NtResumeThread(thread, NULL);
ok_(__FILE__,line)(!status, "NtResumeThread failed, last error:%u\n", GetLastError());
CloseHandle(thread);
ok_(__FILE__,line)(WaitForDebugEvent(&de1, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError());
ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de1.dwDebugEventCode,
"delayed event differ, code:%x was:%x\n", de1.dwDebugEventCode, ctx->ev.dwDebugEventCode);
ok_(__FILE__,line)(ctx->ev.dwProcessId == de1.dwProcessId,
"delayed event differ, pid:%x was:%x\n", de1.dwProcessId, ctx->ev.dwProcessId);
ok_(__FILE__,line)(ctx->ev.dwThreadId == de1.dwThreadId,
"delayed event differ, tid:%x was:%x\n", de1.dwThreadId, ctx->ev.dwThreadId);
}
- }
+}
- #define next_event(a,b) next_event_(__LINE__,a,b) static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout) {
@@ -1273,7 +1323,11 @@ static void test_debugger(const char *argv0) next_event(&ctx, WAIT_EVENT_TIMEOUT); ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); wait_for_breakpoint(&ctx);
- do next_event(&ctx, POLL_EVENT_TIMEOUT);
do
{
test_reply_later(&ctx);
next_event(&ctx, POLL_EVENT_TIMEOUT);
} while(ctx.ev.dwDebugEventCode != -1);
mem = VirtualAllocEx(pi.hProcess, NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
@@ -1297,6 +1351,7 @@ static void test_debugger(const char *argv0) debuggee_thread = get_debuggee_thread(&ctx, ctx.ev.dwThreadId);
wait_for_breakpoint(&ctx);
test_reply_later(&ctx); fetch_thread_context(debuggee_thread); ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == thread_proc, "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress);
@@ -1304,8 +1359,11 @@ static void test_debugger(const char *argv0) get_ip(&debuggee_thread->ctx));
single_step(&ctx, debuggee_thread, thread_proc + 2);
test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc + 3);
test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc);
test_reply_later(&ctx); byte = 0xc3; /* ret */ ret = WriteProcessMemory(pi.hProcess, thread_proc, &byte, 1, NULL);
@@ -1328,6 +1386,7 @@ static void test_debugger(const char *argv0) ok(thread != NULL, "CreateRemoteThread failed: %u\n", GetLastError()); expect_event(&ctx, CREATE_THREAD_DEBUG_EVENT); expect_breakpoint_exception(&ctx, NULL);
test_reply_later(&ctx); expect_event(&ctx, EXIT_THREAD_DEBUG_EVENT); /* BREAKPOINT_PROMPT */
@@ -1422,6 +1481,7 @@ static void test_debugger(const char *argv0)
do {
test_reply_later(&ctx); next_event(&ctx, WAIT_EVENT_TIMEOUT); ok (ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "got exception\n"); }
I wanted to avoid the multithread scenario where another thread may raise an exception when they are resumed, but it looks like I may have missed some Windows quirks that occur on w1064 tests... The other failures are preexisting afaics.