Alexandre Julliard : ntdll: Close the debug port on thread exit.
Alexandre Julliard
julliard at winehq.org
Thu Feb 11 15:37:14 CST 2021
Module: wine
Branch: master
Commit: 7163c78234ecce7e2b5aa531927f573c7d4e5d54
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7163c78234ecce7e2b5aa531927f573c7d4e5d54
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Feb 11 14:17:03 2021 +0100
ntdll: Close the debug port on thread exit.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernel32/tests/debugger.c | 95 ++++++++++++++++++++++++++++++++++++++----
dlls/ntdll/loader.c | 2 +
dlls/ntdll/thread.c | 1 -
3 files changed, 90 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c
index 55bcd62f379..118984eec75 100644
--- a/dlls/kernel32/tests/debugger.c
+++ b/dlls/kernel32/tests/debugger.c
@@ -1779,12 +1779,49 @@ static char *cmd;
static DWORD WINAPI debug_and_exit(void *arg)
{
STARTUPINFOA si = { sizeof(si) };
+ HANDLE debug;
+ ULONG val = 0;
+ NTSTATUS status;
BOOL ret;
ret = CreateProcessA(NULL, cmd, NULL, NULL, TRUE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
+ debug = pDbgUiGetThreadDebugObject();
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( !status, "NtSetInformationDebugObject failed %x\n", status );
+ *(HANDLE *)arg = debug;
Sleep(200);
+ ExitThread(0);
+}
+
+static DWORD WINAPI debug_and_wait(void *arg)
+{
+ STARTUPINFOA si = { sizeof(si) };
+ HANDLE debug = *(HANDLE *)arg;
+ ULONG val = 0;
+ NTSTATUS status;
+ BOOL ret;
+
+ pDbgUiSetThreadDebugObject( debug );
+ ret = CreateProcessA(NULL, cmd, NULL, NULL, TRUE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
+ ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
+ debug = pDbgUiGetThreadDebugObject();
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( !status, "NtSetInformationDebugObject failed %x\n", status );
+ Sleep(INFINITE);
+ ExitThread(0);
+}
+
+static DWORD WINAPI create_debug_port(void *arg)
+{
+ STARTUPINFOA si = { sizeof(si) };
+ NTSTATUS status = pDbgUiConnectToDbg();
+
+ ok( !status, "DbgUiConnectToDbg failed %x\n", status );
*(HANDLE *)arg = pDbgUiGetThreadDebugObject();
+ Sleep( INFINITE );
ExitThread(0);
}
@@ -1844,19 +1881,23 @@ static void test_kill_on_exit(const char *argv0)
exit_code = run_child_wait( cmd, event );
ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08x\n", exit_code);
- /* test that threads don't close the debug port on exit */
+ /* test that threads close the debug port on exit */
thread = CreateThread(NULL, 0, debug_and_exit, &debug, 0, &tid);
WaitForSingleObject( thread, 1000 );
ok( debug != 0, "no debug port\n" );
- SetEvent( event );
- WaitForSingleObject( pi.hProcess, 100 );
- GetExitCodeProcess( pi.hProcess, &exit_code );
- ok( exit_code == STILL_ACTIVE, "exit code = %08x\n", exit_code);
val = 0;
status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
&val, sizeof(val), NULL );
- ok( !status, "NtSetInformationDebugObject failed %x\n", status );
- CloseHandle( debug );
+ ok( status == STATUS_INVALID_HANDLE || broken(status == STATUS_SUCCESS), /* wow64 */
+ "NtSetInformationDebugObject failed %x\n", status );
+ SetEvent( event );
+ if (!status)
+ {
+ WaitForSingleObject( pi.hProcess, 100 );
+ GetExitCodeProcess( pi.hProcess, &exit_code );
+ ok( exit_code == STILL_ACTIVE, "exit code = %08x\n", exit_code);
+ CloseHandle( debug );
+ }
WaitForSingleObject( pi.hProcess, 1000 );
GetExitCodeProcess( pi.hProcess, &exit_code );
ok( exit_code == 0, "exit code = %08x\n", exit_code);
@@ -1864,6 +1905,46 @@ static void test_kill_on_exit(const char *argv0)
CloseHandle( pi.hThread );
CloseHandle( thread );
+ /* but not on forced exit */
+ status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
+ ok( !status, "NtCreateDebugObject failed %x\n", status );
+ thread = CreateThread(NULL, 0, debug_and_wait, &debug, 0, &tid);
+ Sleep( 100 );
+ ok( debug != 0, "no debug port\n" );
+ val = 1;
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %x\n", status );
+ TerminateThread( thread, 0 );
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %x\n", status );
+ WaitForSingleObject( pi.hProcess, 300 );
+ GetExitCodeProcess( pi.hProcess, &exit_code );
+ todo_wine
+ ok( exit_code == STATUS_DEBUGGER_INACTIVE || broken(exit_code == STILL_ACTIVE), /* wow64 */
+ "exit code = %08x\n", exit_code);
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+ CloseHandle( thread );
+ CloseHandle( debug );
+
+ debug = 0;
+ thread = CreateThread(NULL, 0, create_debug_port, &debug, 0, &tid);
+ Sleep(100);
+ ok( debug != 0, "no debug port\n" );
+ val = 0;
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %x\n", status );
+ TerminateThread( thread, 0 );
+ status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
+ &val, sizeof(val), NULL );
+ ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %x\n", status );
+ CloseHandle( debug );
+ CloseHandle( thread );
+
+ CloseHandle( event );
heap_free(cmd);
}
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 378b812868c..84cb7a04ba0 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -3278,6 +3278,8 @@ void WINAPI LdrShutdownThread(void)
RtlReleasePebLock();
RtlLeaveCriticalSection( &loader_section );
+ if (DbgUiGetThreadDebugObject()) NtClose( DbgUiGetThreadDebugObject() );
+ RtlFreeThreadActivationContextStack();
}
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 8e5a3a3a3a3..425e8770294 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -85,7 +85,6 @@ void WINAPI RtlExitUserThread( ULONG status )
NtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread, &last, sizeof(last), NULL );
if (last) RtlExitUserProcess( status );
LdrShutdownThread();
- RtlFreeThreadActivationContextStack();
for (;;) NtTerminateThread( GetCurrentThread(), status );
}
More information about the wine-cvs
mailing list