diff --git a/sycl/source/detail/global_handler.cpp b/sycl/source/detail/global_handler.cpp index c4cb4394c39ab..3cee0563c6e63 100644 --- a/sycl/source/detail/global_handler.cpp +++ b/sycl/source/detail/global_handler.cpp @@ -150,7 +150,8 @@ extern "C" __SYCL_EXPORT BOOL WINAPI DllMain(HINSTANCE hinstDLL, // Perform actions based on the reason for calling. switch (fdwReason) { case DLL_PROCESS_DETACH: - shutdown(); + if (!lpReserved) + shutdown(); break; case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: diff --git a/sycl/unittests/CMakeLists.txt b/sycl/unittests/CMakeLists.txt index 3efd330c112c5..163f139c42737 100644 --- a/sycl/unittests/CMakeLists.txt +++ b/sycl/unittests/CMakeLists.txt @@ -24,3 +24,4 @@ add_subdirectory(thread_safety) add_subdirectory(program_manager) add_subdirectory(assert) add_subdirectory(Extensions) +add_subdirectory(windows) diff --git a/sycl/unittests/windows/CMakeLists.txt b/sycl/unittests/windows/CMakeLists.txt new file mode 100644 index 0000000000000..6143d5de55045 --- /dev/null +++ b/sycl/unittests/windows/CMakeLists.txt @@ -0,0 +1,4 @@ +add_sycl_unittest(WindowsDllMainTest OBJECT + dllmain.cpp +) + diff --git a/sycl/unittests/windows/dllmain.cpp b/sycl/unittests/windows/dllmain.cpp new file mode 100644 index 0000000000000..0e46f0eea9483 --- /dev/null +++ b/sycl/unittests/windows/dllmain.cpp @@ -0,0 +1,65 @@ +//==----- dllmain.cpp --- verify behaviour of lib on process termination ---==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* + * This test calls DllMain on Windows. This means, the process performs actions + * which are required for library unload. That said, the test requires to be a + * distinct binary executable. + */ + +#include +#include +#include +#include + +#include + +#ifdef _WIN32 +#include + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, + LPVOID lpReserved); + +static std::atomic TearDownCalls{0}; + +pi_result redefinedTearDown(void *PluginParameter) { + fprintf(stderr, "intercepted tear down\n"); + ++TearDownCalls; + + return PI_SUCCESS; +} +#endif + +TEST(Windows, DllMainCall) { +#ifdef _WIN32 + sycl::platform Plt{sycl::default_selector()}; + if (Plt.is_host()) { + printf("Test is not supported on host, skipping\n"); + return; + } + sycl::unittest::PiMock Mock{Plt}; + setupDefaultMockAPIs(Mock); + Mock.redefine(redefinedTearDown); + + // Teardown calls are only expected on sycl.dll library unload, not when + // process gets terminated. + // The first call to DllMain is to simulate library unload. The second one + // is to simulate process termination + fprintf(stderr, "Call DllMain for the first time\n"); + DllMain((HINSTANCE)0, DLL_PROCESS_DETACH, (LPVOID)NULL); + + int TearDownCallsDone = TearDownCalls.load(); + + EXPECT_NE(TearDownCallsDone, 0); + + fprintf(stderr, "Call DllMain for the second time\n"); + DllMain((HINSTANCE)0, DLL_PROCESS_DETACH, (LPVOID)0x01); + + EXPECT_EQ(TearDownCalls.load(), TearDownCallsDone); +#endif +}