Zebediah Figura : kernel32/tests: Add a regression test for a deadlock calling FLS callbacks on process exit.
Alexandre Julliard
julliard at winehq.org
Thu Jan 7 15:35:59 CST 2021
Module: wine
Branch: master
Commit: 9bc3a9f78bf5e6a09d4e9811f645def4a477f3d0
URL: https://source.winehq.org/git/wine.git/?a=commit;h=9bc3a9f78bf5e6a09d4e9811f645def4a477f3d0
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Thu Jan 7 09:51:03 2021 -0600
kernel32/tests: Add a regression test for a deadlock calling FLS callbacks on process exit.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernel32/tests/fiber.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c
index 1b5d0d1393a..3c54351fa7b 100644
--- a/dlls/kernel32/tests/fiber.c
+++ b/dlls/kernel32/tests/fiber.c
@@ -776,8 +776,76 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
test_ConvertFiberToThread();
}
+static void WINAPI fls_exit_deadlock_callback(void *arg)
+{
+ if (arg == (void *)1)
+ Sleep(INFINITE);
+ if (arg == (void *)2)
+ /* Unfortunately this test won't affect the exit code if it fails, but
+ * at least it will print a failure message. */
+ ok(RtlDllShutdownInProgress(), "expected DLL shutdown\n");
+}
+
+static DWORD CALLBACK fls_exit_deadlock_thread(void *arg)
+{
+ FlsSetValue((DWORD_PTR)arg, (void *)1);
+ return 0;
+}
+
+static void fls_exit_deadlock_child(void)
+{
+ DWORD index = FlsAlloc(fls_exit_deadlock_callback);
+ FlsSetValue(index, (void *)2);
+ CreateThread(NULL, 0, fls_exit_deadlock_thread, (void *)(DWORD_PTR)index, 0, NULL);
+ Sleep(100);
+ ExitProcess(0);
+}
+
+static void test_fls_exit_deadlock(void)
+{
+ char **argv, cmdline[MAX_PATH];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOA si = {0};
+ BOOL ret;
+
+ /* Regression test for the following deadlock:
+ *
+ * Thread A Thread B
+ * -----------------------------
+ * ExitThread
+ * acquire FLS lock
+ * call FLS callback
+ * ExitProcess
+ * terminate thread A
+ * acquire FLS lock
+ *
+ * Thread B deadlocks on acquiring the FLS lock (in order to itself call its
+ * FLS callbacks.)
+ */
+
+ winetest_get_mainargs(&argv);
+ sprintf(cmdline, "%s %s fls_exit_deadlock", argv[0], argv[1]);
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "failed to create child, error %u\n", GetLastError());
+ ret = WaitForSingleObject(pi.hProcess, 1000);
+ ok(!ret, "wait failed\n");
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+}
+
START_TEST(fiber)
{
+ char **argv;
+ int argc;
+
+ argc = winetest_get_mainargs(&argv);
+
+ if (argc == 3 && !strcmp(argv[2], "fls_exit_deadlock"))
+ {
+ fls_exit_deadlock_child();
+ return;
+ }
+
init_funcs();
if (!pCreateFiber)
@@ -790,4 +858,5 @@ START_TEST(fiber)
test_FiberLocalStorage();
test_FiberLocalStorageCallback(FiberLocalStorageProc);
test_FiberLocalStorageWithFibers(FiberLocalStorageProc);
+ test_fls_exit_deadlock();
}
More information about the wine-cvs
mailing list