Piotr Caban : server: Don' t debug children when debugger is attached with DebugActiveProcess function .

Alexandre Julliard julliard at winehq.org
Fri Apr 5 14:02:16 CDT 2013


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Apr  5 14:08:02 2013 +0200

server: Don't debug children when debugger is attached with DebugActiveProcess function.

---

 dlls/kernel32/tests/debugger.c |  151 ++++++++++++++++++++++++++++++++++++++++
 server/process.c               |    2 +-
 2 files changed, 152 insertions(+), 1 deletions(-)

diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c
index 22f7190..e578cdd 100644
--- a/dlls/kernel32/tests/debugger.c
+++ b/dlls/kernel32/tests/debugger.c
@@ -666,6 +666,150 @@ static void test_debug_loop(int argc, char **argv)
     ok(ret, "DeleteFileA failed, last error %#x.\n", GetLastError());
 }
 
+static void doChildren(int argc, char **argv)
+{
+    const char *arguments = "debugger children last";
+    struct child_blackbox blackbox;
+    const char *blackbox_file, *p;
+    char event_name[MAX_PATH];
+    PROCESS_INFORMATION pi;
+    STARTUPINFOA si;
+    HANDLE event;
+    char *cmd;
+    BOOL ret;
+
+    if (!strcmp(argv[3], "last")) return;
+
+    blackbox_file = argv[3];
+
+    p = strrchr(blackbox_file, '\\');
+    p = p ? p+1 : blackbox_file;
+    strcpy(event_name, p);
+    strcat(event_name, "_init");
+    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name);
+    child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
+    SetEvent(event);
+    CloseHandle(event);
+
+    p = strrchr(blackbox_file, '\\');
+    p = p ? p+1 : blackbox_file;
+    strcpy(event_name, p);
+    strcat(event_name, "_attach");
+    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name);
+    child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
+    WaitForSingleObject(event, INFINITE);
+    CloseHandle(event);
+
+    cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + 2);
+    sprintf(cmd, "%s %s", argv[0], arguments);
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    child_ok(ret, "CreateProcess failed, last error %d.\n", GetLastError());
+
+    child_ok(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0,
+            "Timed out waiting for the child to exit\n");
+
+    ret = CloseHandle(pi.hThread);
+    child_ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
+    ret = CloseHandle(pi.hProcess);
+    child_ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
+
+    blackbox.failures = child_failures;
+    save_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
+}
+
+static void test_debug_children(char *name, DWORD flag, BOOL debug_child)
+{
+    const char *arguments = "debugger children";
+    struct child_blackbox blackbox;
+    char blackbox_file[MAX_PATH], *p;
+    char event_name[MAX_PATH];
+    PROCESS_INFORMATION pi;
+    STARTUPINFOA si;
+    HANDLE event_init, event_attach;
+    char *cmd;
+    BOOL debug, ret;
+    BOOL got_child_event = FALSE;
+
+    if (!pDebugActiveProcessStop || !pCheckRemoteDebuggerPresent)
+    {
+        win_skip("DebugActiveProcessStop or CheckRemoteDebuggerPresent not available, skipping test.\n");
+        return;
+    }
+
+    get_file_name(blackbox_file);
+    cmd = HeapAlloc(GetProcessHeap(), 0, strlen(name) + strlen(arguments) + strlen(blackbox_file) + 5);
+    sprintf(cmd, "%s %s \"%s\"", name, arguments, blackbox_file);
+
+    p = strrchr(blackbox_file, '\\');
+    p = p ? p+1 : blackbox_file;
+    strcpy(event_name, p);
+    strcat(event_name, "_init");
+    event_init = CreateEvent(NULL, FALSE, FALSE, event_name);
+    ok(event_init != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
+
+    p = strrchr(blackbox_file, '\\');
+    p = p ? p+1 : blackbox_file;
+    strcpy(event_name, p);
+    strcat(event_name, "_attach");
+    event_attach = CreateEvent(NULL, FALSE, flag!=0, event_name);
+    ok(event_attach != NULL, "CreateEvent failed, last error %d.\n", GetLastError());
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+
+    ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, flag, NULL, NULL, &si, &pi);
+    ok(ret, "CreateProcess failed, last error %d.\n", GetLastError());
+    HeapFree(GetProcessHeap(), 0, cmd);
+    if (!flag)
+    {
+        WaitForSingleObject(event_init, INFINITE);
+        ret = DebugActiveProcess(pi.dwProcessId);
+        ok(ret, "DebugActiveProcess failed, last error %d.\n", GetLastError());
+        ret = SetEvent(event_attach);
+        ok(ret, "SetEvent failed, last error %d.\n", GetLastError());
+    }
+
+    ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
+    ok(ret, "CheckRemoteDebuggerPresent failed, last error %d.\n", GetLastError());
+    ok(debug, "Expected debug != 0, got %x.\n", debug);
+
+    for (;;)
+    {
+        DEBUG_EVENT ev;
+
+        ret = WaitForDebugEvent(&ev, INFINITE);
+        ok(ret, "WaitForDebugEvent failed, last error %d.\n", GetLastError());
+        if (!ret) break;
+
+        if (ev.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT && ev.dwProcessId==pi.dwProcessId) break;
+        else if (ev.dwProcessId != pi.dwProcessId) got_child_event = TRUE;
+
+        ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
+        ok(ret, "ContinueDebugEvent failed, last error %d.\n", GetLastError());
+        if (!ret) break;
+    }
+    if(debug_child)
+        ok(got_child_event, "didn't get any child events (flag: %x).\n", flag);
+    else
+        ok(!got_child_event, "got child event (flag: %x).\n", flag);
+    CloseHandle(event_init);
+    CloseHandle(event_attach);
+
+    ret = CloseHandle(pi.hThread);
+    ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
+    ret = CloseHandle(pi.hProcess);
+    ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
+
+    load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
+    ok(!blackbox.failures, "Got %d failures from child process.\n", blackbox.failures);
+
+    ret = DeleteFileA(blackbox_file);
+    ok(ret, "DeleteFileA failed, last error %d.\n", GetLastError());
+}
+
 START_TEST(debugger)
 {
     HMODULE hdll;
@@ -691,10 +835,17 @@ START_TEST(debugger)
     {
         doChild(myARGC, myARGV);
     }
+    else if (myARGC >= 4 && !strcmp(myARGV[2], "children"))
+    {
+        doChildren(myARGC, myARGV);
+    }
     else
     {
         test_ExitCode();
         test_RemoteDebugger();
         test_debug_loop(myARGC, myARGV);
+        test_debug_children(myARGV[0], DEBUG_PROCESS, TRUE);
+        test_debug_children(myARGV[0], DEBUG_ONLY_THIS_PROCESS, FALSE);
+        test_debug_children(myARGV[0], 0, FALSE);
     }
 }
diff --git a/server/process.c b/server/process.c
index 058538f..4f04a23 100644
--- a/server/process.c
+++ b/server/process.c
@@ -947,7 +947,7 @@ DECL_HANDLER(new_process)
 
     if (!(thread = create_process( socket_fd, current, req->inherit_all ))) goto done;
     process = thread->process;
-    process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
+    process->debug_children = !!(req->create_flags & DEBUG_PROCESS);
     process->startup_info = (struct startup_info *)grab_object( info );
 
     /* connect to the window station */




More information about the wine-cvs mailing list