l0_feature: Use L0 Loader teardown callback

Related-To: LOCI-4174

- Call zelSetDriverTeardown during L0 Driver teardown to prevent users
from calling into destroyed functions and encountering crashes
during teardown.

Signed-off-by: Neil R Spruit <neil.r.spruit@intel.com>
This commit is contained in:
Neil R Spruit 2023-03-22 01:22:13 +00:00 committed by Compute-Runtime-Automation
parent ac7a5376f2
commit d31b950b9a
19 changed files with 217 additions and 25 deletions

View File

@ -8,6 +8,8 @@ target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/get_extension_function_lookup_map.h
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown.h
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}get_extension_function_lookup_map.cpp
)

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/core/source/global_teardown.h"
#include "shared/source/os_interface/os_library.h"
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/sysman/source/sysman_driver_handle_imp.h"
namespace L0 {
ze_result_t loaderDriverTeardown(std::string loaderLibraryName) {
std::unique_ptr<NEO::OsLibrary> loaderLibrary = std::unique_ptr<NEO::OsLibrary>{NEO::OsLibrary::load(loaderLibraryName.c_str())};
if (loaderLibrary) {
zelSetDriverTeardown_fn setDriverTeardown = reinterpret_cast<zelSetDriverTeardown_fn>(loaderLibrary->getProcAddress("zelSetDriverTeardown"));
if (setDriverTeardown) {
return setDriverTeardown();
}
}
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
void globalDriverTeardown() {
if (GlobalDriver != nullptr) {
delete GlobalDriver;
GlobalDriver = nullptr;
}
if (Sysman::GlobalSysmanDriver != nullptr) {
delete Sysman::GlobalSysmanDriver;
Sysman::GlobalSysmanDriver = nullptr;
}
}
} // namespace L0

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <level_zero/ze_api.h>
#include <string>
namespace L0 {
using zelSetDriverTeardown_fn = ze_result_t (*)();
static const std::string loaderLibraryFilename = "ze_loader";
void globalDriverTeardown();
ze_result_t loaderDriverTeardown(std::string loaderLibraryName);
} // namespace L0

View File

@ -5,18 +5,12 @@
*
*/
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/sysman/source/sysman_driver_handle_imp.h"
#include "level_zero/core/source/global_teardown.h"
using namespace L0;
void __attribute__((destructor)) driverHandleDestructor() {
if (GlobalDriver != nullptr) {
delete GlobalDriver;
GlobalDriver = nullptr;
}
if (Sysman::GlobalSysmanDriver != nullptr) {
delete Sysman::GlobalSysmanDriver;
Sysman::GlobalSysmanDriver = nullptr;
}
std::string loaderLibraryName = "lib" + L0::loaderLibraryFilename + ".so.1";
loaderDriverTeardown(loaderLibraryName);
globalDriverTeardown();
}

View File

@ -5,8 +5,7 @@
*
*/
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/sysman/source/sysman_driver_handle_imp.h"
#include "level_zero/core/source/global_teardown.h"
#include "level_zero/tools/source/sysman/os_sysman_driver.h"
#include "level_zero/tools/source/sysman/sysman.h"
@ -16,14 +15,9 @@ using namespace L0;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_DETACH) {
if (GlobalDriver != nullptr) {
delete GlobalDriver;
GlobalDriver = nullptr;
}
if (Sysman::GlobalSysmanDriver != nullptr) {
delete Sysman::GlobalSysmanDriver;
Sysman::GlobalSysmanDriver = nullptr;
}
std::string loaderLibraryName = L0::loaderLibraryFilename + ".dll";
loaderDriverTeardown(loaderLibraryName);
globalDriverTeardown();
if (GlobalOsSysmanDriver != nullptr) {
delete GlobalOsSysmanDriver;
GlobalOsSysmanDriver = nullptr;

View File

@ -40,3 +40,4 @@ apply_macro_for_each_core_type("TESTED")
add_custom_target(l0_common_test_kernels DEPENDS ${l0_test_kernel_outputs} ${l0_bindless_test_kernel_outputs} copy_compiler_files)
set_target_properties(l0_common_test_kernels PROPERTIES FOLDER ${TARGET_NAME_L0})
add_dependencies(prepare_test_kernels_for_l0 l0_common_test_kernels)
add_subdirectories()

View File

@ -0,0 +1,21 @@
#
# Copyright (C) 2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
project(test_l0_loader_lib)
if(WIN32)
set(OS_SUFFIX win)
else()
set(OS_SUFFIX lin)
endif()
add_library(test_l0_loader_lib SHARED test_l0_loader_lib_${OS_SUFFIX}.cpp)
create_project_source_tree(test_l0_loader_lib)
set_target_properties(test_l0_loader_lib PROPERTIES FOLDER "test mocks")
set_property(TARGET test_l0_loader_lib APPEND_STRING PROPERTY COMPILE_FLAGS ${ASAN_FLAGS})

View File

@ -0,0 +1,12 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include <level_zero/ze_api.h>
extern "C" __attribute__((visibility("default"))) ze_result_t zelSetDriverTeardown() {
return ZE_RESULT_SUCCESS;
}

View File

@ -0,0 +1,12 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include <level_zero/ze_api.h>
extern "C" __declspec(dllexport) ze_result_t zelSetDriverTeardown() {
return ZE_RESULT_SUCCESS;
}

View File

@ -102,6 +102,6 @@ if(MSVC)
)
endif()
add_dependencies(unit_tests ${TARGET_NAME} prepare_test_kernels_for_l0)
add_dependencies(unit_tests ${TARGET_NAME} prepare_test_kernels_for_l0 test_l0_loader_lib)
create_source_tree(${TARGET_NAME} ${L0_ROOT_DIR}/..)

View File

@ -173,6 +173,25 @@ int main(int argc, char **argv) {
sysmanUltsEnable = (strcmp(sysmanUltsEnableEnv, "1") == 0);
}
#if defined(__linux__)
if (getenv("NEO_L0_TEST_SELF_EXEC") == nullptr) {
std::string wd = getRunPath(argv[0]);
char *ldLibraryPath = getenv("LD_LIBRARY_PATH");
if (ldLibraryPath == nullptr) {
setenv("LD_LIBRARY_PATH", wd.c_str(), 1);
} else {
std::string ldLibraryPathConcat = wd + ":" + std::string(ldLibraryPath);
setenv("LD_LIBRARY_PATH", ldLibraryPathConcat.c_str(), 1);
}
setenv("NEO_L0_TEST_SELF_EXEC", wd.c_str(), 1);
execv(argv[0], argv);
printf("FATAL ERROR: cannot self-exec test: %s!, errno: %d\n", argv[0], errno);
return -1;
}
#endif
applyWorkarounds();
testing::InitGoogleMock(&argc, argv);

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2021 Intel Corporation
# Copyright (C) 2021-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@ -7,6 +7,8 @@
set(NEO_L0_OS_INTERFACE_TESTS
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_context_l0_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown_tests.h
)
add_subdirectories()

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/core/test/unit_tests/os_interface/global_teardown_tests.h"
#include "shared/test/common/test_macros/test.h"
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/core/source/global_teardown.h"
#include "level_zero/sysman/source/sysman_driver_handle_imp.h"
namespace L0 {
namespace ult {
TEST(GlobalTearDownCallbackTests, givenL0LoaderThenGlobalTeardownCallbackIsCalled) {
EXPECT_EQ(ZE_RESULT_SUCCESS, loaderDriverTeardown(L0::ult::testLoaderDllName));
}
TEST(GlobalTearDownCallbackTests, givenL0LoaderIsMissingThenGlobalTeardownCallbackIsNotCalled) {
EXPECT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, loaderDriverTeardown("invalid.so"));
}
TEST(GlobalTearDownCallbackTests, givenL0LoaderWithoutGlobalTeardownCallbackThenGlobalTeardownCallbackIsNotCalled) {
EXPECT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, loaderDriverTeardown(L0::ult::testDllName));
}
TEST(GlobalTearDownTests, givenCallToGlobalTearDownFunctionThenGlobalDriversAreNull) {
globalDriverTeardown();
EXPECT_EQ(GlobalDriver, nullptr);
EXPECT_EQ(Sysman::GlobalSysmanDriver, nullptr);
}
} // namespace ult
} // namespace L0

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
namespace L0 {
namespace ult {
extern const char *testLoaderDllName;
extern const char *testDllName;
} // namespace ult
} // namespace L0

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2022 Intel Corporation
# Copyright (C) 2022-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@ -8,5 +8,6 @@ if(UNIX)
target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/cmdqueue_linux_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown_test_values.cpp
)
endif()

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
namespace L0 {
namespace ult {
const char *testLoaderDllName = "libtest_l0_loader_lib.so";
const char *testDllName = "libtest_dynamic_lib.so";
} // namespace ult
} // namespace L0

View File

@ -8,5 +8,6 @@ if(WIN32)
target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/wddm_l0_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_teardown_test_values.cpp
)
endif()

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
namespace L0 {
namespace ult {
const char *testLoaderDllName = "test_l0_loader_lib.dll";
const char *testDllName = "test_dynamic_lib.dll";
} // namespace ult
} // namespace L0

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Intel Corporation
* Copyright (C) 2021-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -25,7 +25,8 @@ void *dlopen(const char *filename, int flags) {
dlopenError = -1;
if (filename == nullptr ||
strcmp(filename, "libtest_dynamic_lib.so") == 0) {
(strcmp(filename, "libtest_dynamic_lib.so") == 0) ||
(strcmp(filename, "libtest_l0_loader_lib.so") == 0)) {
return dlopenFunc(filename, flags);
}
if (filename[0] == '_') {