Skip to content

Commit f179fb4

Browse files
committed
Ensure explicit multidriver teardown during context destroy
- When multiple drivers are present, delayed init did not always update the handles in the alldrivers such that the drivers were unloaded at teardown. To fix this, the loader now creates a unique list of driver library handles opened during the process that need to be released during context destruction. - Unit tests added to ensure this functionality continues to operate correctly. Signed-off-by: Neil R. Spruit <[email protected]>
1 parent 182ff91 commit f179fb4

File tree

3 files changed

+554
-15
lines changed

3 files changed

+554
-15
lines changed

source/loader/ze_loader.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2019-2025 Intel Corporation
3+
* Copyright (C) 2019-2026 Intel Corporation
44
*
55
* SPDX-License-Identifier: MIT
66
*
@@ -9,6 +9,7 @@
99

1010
#include "driver_discovery.h"
1111
#include <iostream>
12+
#include <set>
1213

1314
#ifdef __linux__
1415
#include <unistd.h>
@@ -824,18 +825,36 @@ namespace loader
824825
}
825826
}
826827

827-
for( auto& drv : allDrivers )
828-
{
828+
// Collect all unique driver handles from allDrivers, zeDrivers, and zesDrivers
829+
// to ensure we free each library exactly once, avoiding double-free issues
830+
std::set<HMODULE> uniqueHandles;
831+
for (const auto& drv : allDrivers) {
829832
if (drv.handle) {
830-
auto free_result = FREE_DRIVER_LIBRARY( drv.handle );
831-
auto failure = FREE_DRIVER_LIBRARY_FAILURE_CHECK(free_result);
832-
if (debugTraceEnabled && failure) {
833-
GET_LIBRARY_ERROR(freeLibraryErrorValue);
834-
if (!freeLibraryErrorValue.empty()) {
835-
std::string errorMessage = "Free Library Failed for " + drv.name + " With ";
836-
debug_trace_message(errorMessage, freeLibraryErrorValue);
837-
freeLibraryErrorValue.clear();
838-
}
833+
uniqueHandles.insert(drv.handle);
834+
}
835+
}
836+
for (const auto& drv : zeDrivers) {
837+
if (drv.handle) {
838+
uniqueHandles.insert(drv.handle);
839+
}
840+
}
841+
for (const auto& drv : zesDrivers) {
842+
if (drv.handle) {
843+
uniqueHandles.insert(drv.handle);
844+
}
845+
}
846+
847+
// Free each unique driver library exactly once
848+
for (auto handle : uniqueHandles)
849+
{
850+
auto free_result = FREE_DRIVER_LIBRARY( handle );
851+
auto failure = FREE_DRIVER_LIBRARY_FAILURE_CHECK(free_result);
852+
if (debugTraceEnabled && failure) {
853+
GET_LIBRARY_ERROR(freeLibraryErrorValue);
854+
if (!freeLibraryErrorValue.empty()) {
855+
std::string errorMessage = "Free Library Failed With ";
856+
debug_trace_message(errorMessage, freeLibraryErrorValue);
857+
freeLibraryErrorValue.clear();
839858
}
840859
}
841860
}

test/CMakeLists.txt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ add_executable(
99
loader_tracing_layer.cpp
1010
)
1111

12-
# Only include driver_ordering_unit_tests for static builds or non-Windows platforms
13-
# as it requires internal loader symbols that are not exported in Windows DLLs
12+
# Only include driver_ordering_unit_tests and driver_teardown_unit_tests for static builds or non-Windows platforms
13+
# as they require internal loader symbols that are not exported in Windows DLLs
1414
if(BUILD_STATIC OR NOT WIN32)
15-
target_sources(tests PRIVATE driver_ordering_unit_tests.cpp)
15+
target_sources(tests PRIVATE
16+
driver_ordering_unit_tests.cpp
17+
driver_teardown_unit_tests.cpp
18+
)
1619
endif()
1720

1821
# For builds on non-Windows platforms, include init_driver_unit_tests
@@ -745,7 +748,28 @@ set_property(TEST driver_ordering_trim_function PROPERTY ENVIRONMENT "ZE_ENABLE_
745748

746749
add_test(NAME driver_ordering_parse_driver_order COMMAND tests --gtest_filter=DriverOrderingHelperFunctionsTest.ParseDriverOrder_*)
747750
set_property(TEST driver_ordering_parse_driver_order PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
751+
# Driver Teardown Unit Tests
752+
add_test(NAME driver_teardown_unit_tests COMMAND tests --gtest_filter=DriverTeardownUnitTest.*)
753+
set_property(TEST driver_teardown_unit_tests PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
754+
755+
# Individual Driver Teardown Unit Tests for better granular reporting
756+
add_test(NAME driver_teardown_basic_collection COMMAND tests --gtest_filter=DriverTeardownUnitTest.NoDrivers_*:DriverTeardownUnitTest.AllNullHandles_*:DriverTeardownUnitTest.SingleDriverInAllDrivers_*:DriverTeardownUnitTest.MultipleUniqueHandlesInAllDrivers_*)
757+
set_property(TEST driver_teardown_basic_collection PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
758+
759+
add_test(NAME driver_teardown_duplicate_handles COMMAND tests --gtest_filter=DriverTeardownUnitTest.SameHandleInAllThreeVectors_*:DriverTeardownUnitTest.MultipleDuplicateHandlesAcrossVectors_*:DriverTeardownUnitTest.SameHandleInZeAndZesOnly_*)
760+
set_property(TEST driver_teardown_duplicate_handles PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
761+
762+
add_test(NAME driver_teardown_handle_distribution COMMAND tests --gtest_filter=DriverTeardownUnitTest.OnlyZeDriversHaveHandles_*:DriverTeardownUnitTest.OnlyZesDriversHaveHandles_*:DriverTeardownUnitTest.DifferentHandlesInEachVector_*)
763+
set_property(TEST driver_teardown_handle_distribution PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
764+
765+
add_test(NAME driver_teardown_realistic_scenarios COMMAND tests --gtest_filter=DriverTeardownUnitTest.SingleDriverScenario_*:DriverTeardownUnitTest.MultipleDriversScenario_*:DriverTeardownUnitTest.PartialInitialization_*:DriverTeardownUnitTest.DifferentDriversInitializedInZeVsZes_*)
766+
set_property(TEST driver_teardown_realistic_scenarios PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
767+
768+
add_test(NAME driver_teardown_edge_cases COMMAND tests --gtest_filter=DriverTeardownUnitTest.MixedNullAndValidHandles_*:DriverTeardownUnitTest.VectorSizeMismatch_*:DriverTeardownUnitTest.LargeNumberOfDrivers_*:DriverTeardownUnitTest.CustomDriverScenario_*)
769+
set_property(TEST driver_teardown_edge_cases PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
748770

771+
add_test(NAME driver_teardown_driver_types COMMAND tests --gtest_filter=DriverTeardownUnitTest.MixedDriverTypes_*:DriverTeardownUnitTest.ComplexRealWorldScenario_*)
772+
set_property(TEST driver_teardown_driver_types PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
749773
# Init Driver Unit Tests
750774
add_test(NAME init_driver_unit_tests COMMAND tests --gtest_filter=InitDriverUnitTest.*)
751775
if (MSVC)

0 commit comments

Comments
 (0)