[PATCH 2/2] ntdll: Don't allow blocking on a critical section during process termination.

Dmitry Timoshkov dmitry at baikal.ru
Tue Aug 7 03:03:16 CDT 2018


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 at 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;
-- 
2.17.1




More information about the wine-devel mailing list