[Fix, Test] (MG_Test, MG_Test/Backend, MG_Test/BackendLoader, MG_Test/Buffer, MG_Test/EGLState, MG_Test/Framebuffer, MG_Test/Gbm, MG_Test/Pipe, MG_Test/Pipeline, MG_Test/Program, MG_Test/Query, MG_Test/SelfTest, MG_Test/ShaderTranspiler, MG_Test/State, MG_Test/Swapchain, MG_Test/Texture, MG_Test/Util, MG_Test/VertexArray, MG_Test/Wire, MG_Util/Async): drain shader compile workers before a test's main returns

- On MSVC the atexit drain deadlocked with a worker registering a static's
  destructor, hanging the shader tests on Windows.
This commit is contained in:
2026-10-15 12:12:24 -04:00
parent 66ef4076c8
commit d3c10f15c3
22 changed files with 96 additions and 64 deletions
@@ -20,7 +20,7 @@ target_include_directories(EsslShaderPassTest PRIVATE
target_link_libraries(
EsslShaderPassTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -36,7 +36,7 @@ target_include_directories(BaseInstanceInjectionTest PRIVATE
target_link_libraries(
BaseInstanceInjectionTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -52,14 +52,14 @@ target_include_directories(ViewportIndexRoutingTest PRIVATE
target_link_libraries(
ViewportIndexRoutingTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
include(GoogleTest)
add_executable(ContextEpochTest ContextEpochTest.cpp)
target_include_directories(ContextEpochTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(ContextEpochTest PRIVATE GTest::gtest_main ${LINK_LIBRARIES})
target_link_libraries(ContextEpochTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(ContextEpochTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
# P3b/P4b R-5: D-K2's dependency rule had six statements and nothing compared them. This binary
@@ -67,7 +67,7 @@ gtest_discover_tests(ContextEpochTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS uni
# (MG_Impl/Pipe, through MG_Pipe) and the server gate (MG_Backend/DirectGLES's resolvers).
add_executable(SubsystemDepsTest SubsystemDepsTest.cpp)
target_include_directories(SubsystemDepsTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(SubsystemDepsTest PRIVATE GTest::gtest_main ${LINK_LIBRARIES})
target_link_libraries(SubsystemDepsTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(SubsystemDepsTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
gtest_discover_tests(EsslShaderPassTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
gtest_discover_tests(BaseInstanceInjectionTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
@@ -41,7 +41,7 @@ target_link_libraries(DirectVulkanSanityTest PRIVATE Vulkan::Vulkan)
target_link_libraries(
DirectVulkanSanityTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
if (APPLE)
@@ -20,7 +20,7 @@ target_include_directories(BackendLoaderTest PRIVATE
target_link_libraries(
BackendLoaderTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+2 -2
View File
@@ -23,7 +23,7 @@ target_include_directories(BufferTest PRIVATE
target_link_libraries(
BufferTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -50,7 +50,7 @@ target_include_directories(SplitBufferTest PRIVATE
target_link_libraries(
SplitBufferTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+8 -2
View File
@@ -29,6 +29,12 @@ FetchContent_Declare(
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
# The main() of every test binary: gtest's, then the shader compile workers stop before main
# returns (see TestMain.cpp).
add_library(MobileGLTestMain STATIC TestMain.cpp)
target_link_libraries(MobileGLTestMain PUBLIC GTest::gtest MobileGL_s)
target_include_directories(MobileGLTestMain PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
enable_testing()
# # Find the required libraries using our custom Find modules
@@ -42,7 +48,7 @@ add_executable(
)
target_link_libraries(
SanityTest
GTest::gtest_main
MobileGLTestMain
MobileGL_s
)
@@ -109,7 +115,7 @@ add_subdirectory(Backend/DirectGLES)
# Which session's submission stops the GPU (MG_Backend/GpuHangWatch.h): no device, no driver.
add_executable(GpuHangWatchTest Backend/GpuHangWatchTest.cpp)
target_include_directories(GpuHangWatchTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(GpuHangWatchTest PRIVATE GTest::gtest_main ${LINK_LIBRARIES})
target_link_libraries(GpuHangWatchTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(GpuHangWatchTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
if (ENABLE_INTEGRATION_TESTS)
add_subdirectory(Backend/DirectVulkan)
+1 -1
View File
@@ -21,7 +21,7 @@ target_include_directories(EGLStateTest PRIVATE
target_link_libraries(
EGLStateTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+1 -1
View File
@@ -20,7 +20,7 @@ target_include_directories(FramebufferTest PRIVATE
target_link_libraries(
FramebufferTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+1 -1
View File
@@ -27,7 +27,7 @@ target_compile_definitions(GbmGlamorTest PRIVATE
MOBILEGL_TEST_GBM_BACKEND_DIR="$<TARGET_FILE_DIR:mobilegl_gbm>"
MOBILEGL_TEST_FAKE_SHARED_IMAGE_LIBRARY="$<TARGET_FILE:mobilegl_fake_shared_images>"
)
target_link_libraries(GbmGlamorTest PRIVATE GTest::gtest_main ${MOBILEGL_TEST_GBM_LIBRARY} ${CMAKE_DL_LIBS})
target_link_libraries(GbmGlamorTest PRIVATE MobileGLTestMain ${MOBILEGL_TEST_GBM_LIBRARY} ${CMAKE_DL_LIBS})
include(GoogleTest)
gtest_discover_tests(GbmGlamorTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
+5 -5
View File
@@ -24,7 +24,7 @@ target_include_directories(PipeCatalogueTest PRIVATE
target_link_libraries(
PipeCatalogueTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -35,13 +35,13 @@ endif()
# P13 W5: the record arm's fail / latch seam, in both library shapes (with and without MG_Remote).
add_executable(RecordFailSeamTest RecordFailSeamTest.cpp)
target_include_directories(RecordFailSeamTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(RecordFailSeamTest PRIVATE GTest::gtest_main ${LINK_LIBRARIES})
target_link_libraries(RecordFailSeamTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(RecordFailSeamTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
# P7 B4 aggregate-wait regression control shares the production selector; no device is needed.
add_executable(MagmaAggregateWaitTest MagmaAggregateWaitTest.cpp)
target_include_directories(MagmaAggregateWaitTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(MagmaAggregateWaitTest PRIVATE GTest::gtest_main ${LINK_LIBRARIES})
target_link_libraries(MagmaAggregateWaitTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(MagmaAggregateWaitTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
# The P1 poison and verify shapes at the block level: a fake GLContext, the real filler and
@@ -95,7 +95,7 @@ foreach(pipeTest TrackerTest SlotAllocatorTest CsoCacheTest)
)
target_link_libraries(${pipeTest} PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -147,7 +147,7 @@ target_include_directories(MagmaPipeIdentityTest PRIVATE
)
target_link_libraries(MagmaPipeIdentityTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+1 -1
View File
@@ -26,7 +26,7 @@ target_include_directories(PipelineQuirkTest PRIVATE
target_link_libraries(
PipelineQuirkTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+16 -16
View File
@@ -27,7 +27,7 @@ target_include_directories(ProgramUtilTest PRIVATE
target_link_libraries(
ProgramUtilTest
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -59,7 +59,7 @@ target_include_directories(AsyncCompileTest PRIVATE
target_link_libraries(
AsyncCompileTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -80,7 +80,7 @@ target_include_directories(OptimisticStatusTest PRIVATE
target_link_libraries(
OptimisticStatusTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -91,7 +91,7 @@ target_include_directories(AsyncLinkTest PRIVATE
target_link_libraries(
AsyncLinkTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -109,7 +109,7 @@ target_include_directories(AsyncSpirvPhaseTest PRIVATE
target_link_libraries(
AsyncSpirvPhaseTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -125,7 +125,7 @@ target_include_directories(ShaderCompileAdoptionTest PRIVATE
target_link_libraries(
ShaderCompileAdoptionTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -141,7 +141,7 @@ target_include_directories(ParallelShaderCompileTest PRIVATE
target_link_libraries(
ParallelShaderCompileTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -160,7 +160,7 @@ target_include_directories(XfbFrontendOrderInvarianceTest PRIVATE
target_link_libraries(
XfbFrontendOrderInvarianceTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -179,7 +179,7 @@ target_include_directories(AsyncTeardownTest PRIVATE
target_link_libraries(
AsyncTeardownTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -195,7 +195,7 @@ target_include_directories(XfbBlockVaryingTest PRIVATE
target_link_libraries(
XfbBlockVaryingTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -211,7 +211,7 @@ target_include_directories(TessellationLinkTest PRIVATE
target_link_libraries(
TessellationLinkTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -227,7 +227,7 @@ target_include_directories(ProgramPipelineCompositeTest PRIVATE
target_link_libraries(
ProgramPipelineCompositeTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -243,7 +243,7 @@ target_include_directories(ProgramInterfaceTest PRIVATE
target_link_libraries(
ProgramInterfaceTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -254,7 +254,7 @@ target_include_directories(ProgramTest PRIVATE
target_link_libraries(
ProgramTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -299,7 +299,7 @@ target_include_directories(ProgramArtifactsTest PRIVATE
target_link_libraries(
ProgramArtifactsTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -322,7 +322,7 @@ target_include_directories(ProgramArtifactsCodecTest PRIVATE
target_link_libraries(
ProgramArtifactsCodecTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+1 -1
View File
@@ -20,7 +20,7 @@ target_include_directories(QueryTest PRIVATE
target_link_libraries(
QueryTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+4 -4
View File
@@ -19,7 +19,7 @@ target_include_directories(DriverPostIterationRPWitnessTest PRIVATE
)
target_link_libraries(DriverPostIterationRPWitnessTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -35,7 +35,7 @@ target_include_directories(DriverBugProbesTest PRIVATE
)
target_link_libraries(DriverBugProbesTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -50,7 +50,7 @@ target_include_directories(PrimitivesGeneratedNoXfbProbeTest PRIVATE
)
target_link_libraries(PrimitivesGeneratedNoXfbProbeTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -78,7 +78,7 @@ target_compile_definitions(BakedInternalShadersTest PRIVATE
)
target_link_libraries(BakedInternalShadersTest PRIVATE
GTest::gtest_main
MobileGLTestMain
glslang
glslang-default-resource-limits
${LINK_LIBRARIES}
@@ -44,7 +44,7 @@ target_include_directories(SpirvPassTest PRIVATE
target_link_libraries(
SpirvPassTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -69,7 +69,7 @@ target_include_directories(TranslationCacheTest PRIVATE
target_link_libraries(
TranslationCacheTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+7 -7
View File
@@ -20,7 +20,7 @@ target_include_directories(DebugTest PRIVATE
target_link_libraries(
DebugTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -42,7 +42,7 @@ target_include_directories(ObjectLifetimeIdTest PRIVATE
target_link_libraries(
ObjectLifetimeIdTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -68,7 +68,7 @@ target_include_directories(TransformFeedbackLifetimeIdTest PRIVATE
target_link_libraries(
TransformFeedbackLifetimeIdTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -93,7 +93,7 @@ target_include_directories(RenderStateTest PRIVATE
target_link_libraries(
RenderStateTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -118,7 +118,7 @@ target_include_directories(NegativeApiErrorsTest PRIVATE
target_link_libraries(
NegativeApiErrorsTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -143,7 +143,7 @@ target_include_directories(MipmapFootprintTest PRIVATE
target_link_libraries(
MipmapFootprintTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -165,7 +165,7 @@ target_include_directories(ContextStateOwnershipTest PRIVATE
target_link_libraries(
ContextStateOwnershipTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+1 -1
View File
@@ -22,7 +22,7 @@ target_include_directories(SwapchainPresentModeTest PRIVATE
target_link_libraries(
SwapchainPresentModeTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+23
View File
@@ -0,0 +1,23 @@
// MobileGL - MobileGL/MG_Test/TestMain.cpp
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#include <gtest/gtest.h>
#include <MG_Util/Async/ShaderCompilePool.h>
// gtest's main, plus one step: the shader compile workers stop before main returns, as an
// application's eglTerminate stops them. Left to the pool's atexit fallback, a worker still
// compiling when the tests end can deadlock the MSVC runtime: the fallback waits for the worker
// while holding the runtime's exit lock, and the worker needs that lock to register the destructor
// of a static it constructs for the first time.
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
const int result = RUN_ALL_TESTS();
MobileGL::MG_Util::Async::ShaderCompilePool::StopAndDrainProcessPoolAtExit();
return result;
}
+2 -2
View File
@@ -20,7 +20,7 @@ target_include_directories(TextureTest PRIVATE
target_link_libraries(
TextureTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -39,7 +39,7 @@ target_include_directories(TextureViewTest PRIVATE
target_link_libraries(
TextureViewTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+6 -6
View File
@@ -20,7 +20,7 @@ target_include_directories(JobNodeTest PRIVATE
target_link_libraries(
JobNodeTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -57,7 +57,7 @@ target_include_directories(PipeStatsTest PRIVATE
target_link_libraries(
PipeStatsTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -75,7 +75,7 @@ target_include_directories(DamageTest PRIVATE
target_link_libraries(
DamageTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -93,7 +93,7 @@ target_include_directories(ConfigFileTest PRIVATE
target_link_libraries(
ConfigFileTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -111,7 +111,7 @@ target_include_directories(X11DisplayGuardTest PRIVATE
target_link_libraries(
X11DisplayGuardTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -130,7 +130,7 @@ target_include_directories(X11PresentTest PRIVATE
target_link_libraries(
X11PresentTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+2 -2
View File
@@ -20,7 +20,7 @@ target_include_directories(VertexArrayTest PRIVATE
target_link_libraries(
VertexArrayTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
@@ -36,7 +36,7 @@ target_include_directories(VertexAttribBindingStateTest PRIVATE
target_link_libraries(
VertexAttribBindingStateTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
+2 -2
View File
@@ -141,7 +141,7 @@ foreach (test IN LISTS MOBILEGL_WIRE_TESTS)
endif ()
target_link_libraries(${test} PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
if (test STREQUAL "ServerSpawnTest")
@@ -293,7 +293,7 @@ if (NOT WIN32)
${MGL_ROOT}/3rdparty/flatbuffers/include
)
target_link_libraries(EventForfeitPeerTest PRIVATE
GTest::gtest_main
MobileGLTestMain
${LINK_LIBRARIES}
)
if (TARGET MobileGLServer)
+4 -1
View File
@@ -53,7 +53,10 @@ namespace MobileGL::MG_Util::Async {
// it just also has to happen for a process that exits without ever
// calling eglTerminate, which is the norm for a test binary and legal
// for an application. Registered here, during main, so it runs before
// the destructors of statics constructed at load time.
// the destructors of statics constructed at load time. The MSVC runtime
// runs this under its exit lock, so a worker that constructs a static for
// the first time meanwhile deadlocks: a program linking MobileGL statically
// drains before main returns, as MG_Test's TestMain.cpp does.
ShaderCompilePool::StopAndDrainProcessPoolAtExit();
});
});