As a result HeapLock() no longer blocks process termination since underlying implementation uses a critical section. However this should be considered as a minor side effect because applications shouldn't depend on this behaviour.
This patch should fix the deadlocks observered during various .net setups, and it appears that this is what Windows does as well.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/kernel32/tests/loader.c | 4 +++- dlls/ntdll/critsection.c | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 46c09d41cb..e4d6741b6f 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -2169,6 +2169,7 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param) * doesn't call the DLL entry point on process detach either. */ HeapLock(GetProcessHeap()); +todo_wine ok(0, "dll_entry_point: process should already deadlock\n"); break; } @@ -3023,6 +3024,7 @@ static void test_ExitProcess(void) ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); ret = WaitForSingleObject(pi.hProcess, 5000); +todo_wine ok(ret == WAIT_TIMEOUT || broken(ret == WAIT_OBJECT_0) /* XP */, "child process should fail to terminate\n"); if (ret != WAIT_OBJECT_0) { @@ -3032,6 +3034,7 @@ static void test_ExitProcess(void) ret = WaitForSingleObject(pi.hProcess, 1000); ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); GetExitCodeProcess(pi.hProcess, &ret); +todo_wine ok(ret == 201 || broken(ret == 1) /* XP */, "expected exit code 201, got %u\n", ret); if (*child_failures) { @@ -3047,7 +3050,6 @@ static void test_ExitProcess(void) ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); ret = WaitForSingleObject(pi.hProcess, 5000); -todo_wine ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n"); if (ret != WAIT_OBJECT_0) { diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c index e405b08a5a..42e432c8f6 100644 --- a/dlls/ntdll/critsection.c +++ b/dlls/ntdll/critsection.c @@ -436,6 +436,15 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) { LONGLONG timeout = NtCurrentTeb()->Peb->CriticalSectionTimeout.QuadPart / -10000000; + + /* Don't allow blocking on a critical section during process termination */ + if (RtlDllShutdownInProgress()) + { + WARN( "process %s is shutting down, returning STATUS_SUCCESS\n", + debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer) ); + return STATUS_SUCCESS; + } + for (;;) { EXCEPTION_RECORD rec;