已合并
fix: 统一管理 Python 解释器生命周期 #3631
duhua创建于 6月22日
fix: 统一管理 Python 解释器生命周期 #3631
已合并
duhua创建于 6月22日
共 31 个文件变更+1016-88
@@ -42,6 +42,7 @@
42#include "api/gelib/gelib.h"42#include "api/gelib/gelib.h"
43#include "graph/preprocess/insert_op/insert_aipp_op_util.h"43#include "graph/preprocess/insert_op/insert_aipp_op_util.h"
44#include "api/aclgrph/option_utils.h"44#include "api/aclgrph/option_utils.h"
45+#include "common/python_runtime/ge_python_runtime_manager.h"
45#include "mmpa/mmpa_api.h"46#include "mmpa/mmpa_api.h"
46#include "common/single_op_parser.h"47#include "common/single_op_parser.h"
47#include "parser/common/op_registration_tbe.h"48#include "parser/common/op_registration_tbe.h"
@@ -811,6 +812,18 @@ class GFlagUtils {
811 return ge::SUCCESS;812 return ge::SUCCESS;
812 }813 }
813 814 
815+ static Status CheckPrecisionRelatedFlags() {
816+ GE_ASSERT_SUCCESS(CheckIsWeightClipParamValid(FLAGS_is_weight_clip), "[Check][is_weight_clip]failed!");
817+ GE_ASSERT_SUCCESS(CheckPrecisionModeParamValid(FLAGS_precision_mode), "[Check][PrecisionMode]failed!");
818+ GE_ASSERT_SUCCESS(CheckPrecisionModeV2ParamValid(FLAGS_precision_mode_v2), "[Check][PrecisionModeV2]failed!");
819+ GE_ASSERT_SUCCESS(CheckPrecisionModeV2Conflict(FLAGS_precision_mode, FLAGS_precision_mode_v2),
820+ "[Check][PrecisionModeV2Conflict]failed!");
821+ if (CheckModifyMixlistParamValid(FLAGS_precision_mode, FLAGS_precision_mode_v2, FLAGS_modify_mixlist) != SUCCESS) {
822+ return FAILED;
823+ }
824+ return SUCCESS;
825+ }
826+ 
814 static Status CheckFlags() {827 static Status CheckFlags() {
815 const bool is_mode_om = ((FLAGS_mode == static_cast<int32_t>(RunMode::GEN_OM_MODEL)) ||828 const bool is_mode_om = ((FLAGS_mode == static_cast<int32_t>(RunMode::GEN_OM_MODEL)) ||
816 (FLAGS_mode == static_cast<int32_t>(RunMode::GEN_EXE_OM_FOR_NANO)) ||829 (FLAGS_mode == static_cast<int32_t>(RunMode::GEN_EXE_OM_FOR_NANO)) ||
@@ -858,14 +871,7 @@ class GFlagUtils {
858 GELOGE(FAILED, "[Check][op_precision_mode] %s not found", FLAGS_op_precision_mode.c_str());871 GELOGE(FAILED, "[Check][op_precision_mode] %s not found", FLAGS_op_precision_mode.c_str());
859 return FAILED;872 return FAILED;
860 }873 }
861- GE_ASSERT_SUCCESS(CheckIsWeightClipParamValid(FLAGS_is_weight_clip), "[Check][is_weight_clip]failed!");874+ GE_ASSERT_SUCCESS(CheckPrecisionRelatedFlags());
862- GE_ASSERT_SUCCESS(CheckPrecisionModeParamValid(FLAGS_precision_mode), "[Check][PrecisionMode]failed!");
863- GE_ASSERT_SUCCESS(CheckPrecisionModeV2ParamValid(FLAGS_precision_mode_v2), "[Check][PrecisionModeV2]failed!");
864- GE_ASSERT_SUCCESS(CheckPrecisionModeV2Conflict(FLAGS_precision_mode, FLAGS_precision_mode_v2),
865- "[Check][PrecisionModeV2Conflict]failed!");
866- if (CheckModifyMixlistParamValid(FLAGS_precision_mode, FLAGS_precision_mode_v2, FLAGS_modify_mixlist) != SUCCESS) {
867- return FAILED;
868- }
869 875 
870 if (CheckAndTransferInputShapeToRange(FLAGS_input_shape, FLAGS_input_shape_range, FLAGS_dynamic_batch_size,876 if (CheckAndTransferInputShapeToRange(FLAGS_input_shape, FLAGS_input_shape_range, FLAGS_dynamic_batch_size,
871 FLAGS_dynamic_image_size, FLAGS_dynamic_dims) != SUCCESS) {877 FLAGS_dynamic_image_size, FLAGS_dynamic_dims) != SUCCESS) {
@@ -1417,6 +1423,7 @@ Status GenerateInfershapeJson() {
1417 DOMI_LOGE("GeGenerator initialize failed!");1423 DOMI_LOGE("GeGenerator initialize failed!");
1418 return FAILED;1424 return FAILED;
1419 }1425 }
1426+ GE_MAKE_GUARD(release_python_runtime, []() { (void)GePythonRuntimeManager::Instance().ShutdownProcess(); });
1420 1427 
1421 Graph graph;1428 Graph graph;
1422 std::map<std::string, std::string> atc_params;1429 std::map<std::string, std::string> atc_params;
@@ -1631,7 +1638,15 @@ Status GenerateModel(std::map<std::string, std::string> &options, const std::str
1631 GeGenerator ge_generator;1638 GeGenerator ge_generator;
1632 Status ret = SUCCESS;1639 Status ret = SUCCESS;
1633 std::shared_ptr<GELib> instance_ptr = GELib::GetInstance();1640 std::shared_ptr<GELib> instance_ptr = GELib::GetInstance();
1641+ bool release_python_runtime = false;
1642+ GE_DISMISSABLE_GUARD(release_python_runtime_guard, ([&release_python_runtime]() {
1643+ if (release_python_runtime) {
1644+ (void)GePythonRuntimeManager::Instance().ShutdownProcess();
1645+ }
1646+ }));
1634 if (instance_ptr == nullptr || !instance_ptr->InitFlag()) {1647 if (instance_ptr == nullptr || !instance_ptr->InitFlag()) {
1648+ GE_ASSERT_SUCCESS(GePythonRuntimeManager::Instance().EnsureReady());
1649+ release_python_runtime = true;
1635 ret = GELib::Initialize(options);1650 ret = GELib::Initialize(options);
1636 if (ret != SUCCESS) {1651 if (ret != SUCCESS) {
1637 DOMI_LOGE("GE initialize failed!");1652 DOMI_LOGE("GE initialize failed!");
@@ -1647,8 +1662,10 @@ Status GenerateModel(std::map<std::string, std::string> &options, const std::str
1647 const std::function<void()> callback = [&ge_generator]() {1662 const std::function<void()> callback = [&ge_generator]() {
1648 (void)ge_generator.Finalize();1663 (void)ge_generator.Finalize();
1649 (void)GELib::GetInstance()->Finalize();1664 (void)GELib::GetInstance()->Finalize();
1665+ (void)GePythonRuntimeManager::Instance().ShutdownProcess();
1650 };1666 };
1651 GE_MAKE_GUARD(release, callback);1667 GE_MAKE_GUARD(release, callback);
1668+ release_python_runtime = false;
atomgit-bot
atomgit-botatomgit-bot6月24日

🔵 Low Priority

在 api/atc/main_impl.cc 的 GenerateModel 函数中,回调 lambda(第 1656–1660 行)无条件调用 GePythonRuntimeManager::Instance().ShutdownProcess()。

触发条件:当外部组件先调用了 GELib::Initialize()(如通过 GEInitializeV2 链路),此时 instance_ptr->InitFlag() 为 true,GenerateModel 跳过 EnsureReady() 和 GELib::Initialize(),直接进入 ge_generator.Initialize()。但回调中的 ShutdownProcess() 仍然会执行,由于 manager_is_owner_ 为 true(由外部的首次 EnsureReady() 设置),Python 解释器会被错误地 finalize。

影响:在正常 ATC 工具流中此路径不可达(因为每次 GenerateModel 回调都会 finalize GELib,下一次调用时 InitFlag() 为 false)。但如果 GenerateModel 被复用或与其他 GE API 混合使用,会导致 Python 解释器被意外终止。

变更引入点:第 1659 行新增的 GePythonRuntimeManager::Instance().ShutdownProcess() 调用。

建议:将回调中的 ShutdownProcess() 调用改为条件执行:仅当本函数调用了 EnsureReady() 时才 shutdown。可将 release_python_runtime 标志传入回调,或复用已有的 dismissable guard 机制(将 dismissable guard 的回调改为始终有效,移除 callback 中的 ShutdownProcess,通过 dismissable 变量控制)。具体做法:回调中只在 release_python_runtime == true 时调用 ShutdownProcess(),然后移除 release_python_runtime = false 行,因为 dismissable guard 本身已通过 release_python_runtime 控制。

likedislike
不准确?
duhua
duhua
6月24日 评论:
1652 GELOGD("Current input is single graph to generate model.");1669 GELOGD("Current input is single graph to generate model.");
1653 return GenerateModelBySingleGraph(ge_generator, output, options);1670 return GenerateModelBySingleGraph(ge_generator, output, options);
1654}1671}
@@ -1697,7 +1714,7 @@ static void SetEnvForSingleOp(std::map<std::string, std::string> &options) {
1697 SetOptionNameMap(options);1714 SetOptionNameMap(options);
1698}1715}
1699 1716 
1700-Status GenerateSingleOp(const std::string &json_file_path) {1717+Status CheckSingleOpOptions() {
1701 if ((!GFlagUtils::IsRequiredParameterExists("--output", FLAGS_output)) ||1718 if ((!GFlagUtils::IsRequiredParameterExists("--output", FLAGS_output)) ||
1702 (!GFlagUtils::IsRequiredParameterExists("--soc_version", FLAGS_soc_version))) {1719 (!GFlagUtils::IsRequiredParameterExists("--soc_version", FLAGS_soc_version))) {
1703 return FAILED;1720 return FAILED;
@@ -1720,15 +1737,34 @@ Status GenerateSingleOp(const std::string &json_file_path) {
1720 return FAILED;1737 return FAILED;
1721 }1738 }
1722 1739 
1723- GE_ASSERT_SUCCESS(CheckIsWeightClipParamValid(FLAGS_is_weight_clip), "[Check][is_weight_clip]failed!");1740+ GE_ASSERT_SUCCESS(GFlagUtils::CheckPrecisionRelatedFlags());
1724- GE_ASSERT_SUCCESS(CheckPrecisionModeParamValid(FLAGS_precision_mode), "[Check][PrecisionMode]failed!");
1725- GE_ASSERT_SUCCESS(CheckPrecisionModeV2ParamValid(FLAGS_precision_mode_v2), "[Check][PrecisionModeV2]failed!");
1726- GE_ASSERT_SUCCESS(CheckPrecisionModeV2Conflict(FLAGS_precision_mode, FLAGS_precision_mode_v2),
1727- "[Check][PrecisionModeV2Conflict]failed!");
1728- if (CheckModifyMixlistParamValid(FLAGS_precision_mode, FLAGS_precision_mode_v2, FLAGS_modify_mixlist) != SUCCESS) {
1729- return FAILED;
1730- }
1731 GE_ASSERT_SUCCESS(CheckAllowHF32ParamValid(FLAGS_allow_hf32), "[Check][AllowHF32]failed!");1741 GE_ASSERT_SUCCESS(CheckAllowHF32ParamValid(FLAGS_allow_hf32), "[Check][AllowHF32]failed!");
1742+ return SUCCESS;
1743+}
1744+ 
1745+Status BuildSingleOpModels(GeGenerator &generator, std::vector<SingleOpBuildParam> &build_params) {
1746+ Status ret = SUCCESS;
1747+ int32_t index = 0;
1748+ for (auto &param : build_params) {
1749+ std::string output_path;
1750+ if (!FLAGS_output.empty()) {
1751+ output_path = FLAGS_output + "/";
1752+ }
1753+ output_path += param.file_name;
1754+ ret = generator.BuildSingleOpModel(param.op_desc, param.inputs, param.outputs, output_path, param.compile_flag);
1755+ if (ret != SUCCESS) {
1756+ DOMI_LOGE("Compile op failed. ge ret = %u, op index = %d", ret, index);
1757+ ret = FAILED;
1758+ } else {
1759+ GELOGI("Compile op success. op index = %d, output = %s", index, output_path.c_str());
1760+ }
1761+ index += 1;
1762+ }
1763+ return ret;
1764+}
1765+ 
1766+Status GenerateSingleOp(const std::string &json_file_path) {
1767+ GE_ASSERT_SUCCESS(CheckSingleOpOptions());
1732 GE_ASSERT_GRAPH_SUCCESS(OpLibRegistry::GetInstance().PreProcessForCustomOp());1768 GE_ASSERT_GRAPH_SUCCESS(OpLibRegistry::GetInstance().PreProcessForCustomOp());
1733 std::map<std::string, std::string> options;1769 std::map<std::string, std::string> options;
1734 // need to be changed when ge.ini plan is done1770 // need to be changed when ge.ini plan is done
@@ -1736,6 +1772,8 @@ Status GenerateSingleOp(const std::string &json_file_path) {
1736 // print single op option map1772 // print single op option map
1737 PrintOptionMap(options, "single op option");1773 PrintOptionMap(options, "single op option");
1738 1774 
1775+ GE_ASSERT_SUCCESS(GePythonRuntimeManager::Instance().EnsureReady());
1776+ GE_MAKE_GUARD(release_python_runtime, []() { (void)GePythonRuntimeManager::Instance().ShutdownProcess(); });
1739 auto ret = GELib::Initialize(options);1777 auto ret = GELib::Initialize(options);
1740 if (ret != SUCCESS) {1778 if (ret != SUCCESS) {
1741 DOMI_LOGE("GE initialize failed!");1779 DOMI_LOGE("GE initialize failed!");
@@ -1758,23 +1796,7 @@ Status GenerateSingleOp(const std::string &json_file_path) {
1758 return FAILED;1796 return FAILED;
1759 }1797 }
1760 1798 
1761- int32_t index = 0;1799+ ret = BuildSingleOpModels(generator, build_params);
1762- for (auto &param : build_params) {
1763- std::string output_path;
1764- if (!FLAGS_output.empty()) {
1765- output_path = FLAGS_output + "/";
1766- }
1767- output_path += param.file_name;
1768- ret = generator.BuildSingleOpModel(param.op_desc, param.inputs, param.outputs, output_path, param.compile_flag);
1769- if (ret != SUCCESS) {
1770- DOMI_LOGE("Compile op failed. ge ret = %u, op index = %d", ret, index);
1771- ret = FAILED;
1772- } else {
1773- GELOGI("Compile op success. op index = %d, output = %s", index, output_path.c_str());
1774- }
1775- index += 1;
1776- }
1777- 
1778 (void)generator.Finalize();1800 (void)generator.Finalize();
1779 (void)GELib::GetInstance()->Finalize();1801 (void)GELib::GetInstance()->Finalize();
1780 return ret;1802 return ret;
@@ -19,6 +19,7 @@
19#include "common/plugin/tbe_plugin_manager.h"19#include "common/plugin/tbe_plugin_manager.h"
20#include "common/profiling/profiling_init.h"20#include "common/profiling/profiling_init.h"
21#include "common/profiling/profiling_properties.h"21#include "common/profiling/profiling_properties.h"
22+#include "common/python_runtime/ge_python_runtime_manager.h"
22#include "base/err_msg.h"23#include "base/err_msg.h"
23#include "rt_error_codes.h"24#include "rt_error_codes.h"
24#include "ge/ge_api_types.h"25#include "ge/ge_api_types.h"
@@ -281,6 +282,9 @@ static Status GEInitializeImpl(const std::map<std::string, std::string> &options
281 std::vector<const char *>({opsproto_path.c_str(), "failed to load the OpsProto lib plugin"}));282 std::vector<const char *>({opsproto_path.c_str(), "failed to load the OpsProto lib plugin"}));
282 return FAILED;283 return FAILED;
283 }284 }
285+ GE_ASSERT_SUCCESS(GePythonRuntimeManager::Instance().EnsureReady());
286+ GE_DISMISSABLE_GUARD(release_python_runtime,
287+ ([]() { (void)GePythonRuntimeManager::Instance().ShutdownProcess(); }));
284 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());288 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());
285 289 
286 ge::GetContext().Init();290 ge::GetContext().Init();
@@ -334,6 +338,7 @@ static Status GEInitializeImpl(const std::map<std::string, std::string> &options
334 if (!g_ge_initialized) {338 if (!g_ge_initialized) {
335 g_ge_initialized = true;339 g_ge_initialized = true;
336 }340 }
341+ GE_DISMISS_GUARD(release_python_runtime);
337 342 
338 GELOGT(TRACE_STOP, "GEInitialize finished");343 GELOGT(TRACE_STOP, "GEInitialize finished");
339 GE_TIMESTAMP_EVENT_END(GEInitializeAll, "GEInitialize::All");344 GE_TIMESTAMP_EVENT_END(GEInitializeAll, "GEInitialize::All");
@@ -408,6 +413,7 @@ Status GEFinalizeV2() {
408 ret = middle_ret;413 ret = middle_ret;
409 }414 }
410 415 
416+ (void)GePythonRuntimeManager::Instance().ShutdownProcess();
411 if (g_ge_initialized && (ret == SUCCESS)) {417 if (g_ge_initialized && (ret == SUCCESS)) {
412 // Unified destruct rt_context418 // Unified destruct rt_context
413 RtContextUtil::GetInstance().DestroyAllRtContexts();419 RtContextUtil::GetInstance().DestroyAllRtContexts();
@@ -37,6 +37,7 @@ set(SRC_FORMAT_TRANSFERS
37)37)
38 38 
39set(SRC_LIST39set(SRC_LIST
40+ "common/python_runtime/ge_python_runtime_manager.cc"
40 "common/b_cast/b_cast.cc"41 "common/b_cast/b_cast.cc"
41 "common/plugin/runtime_plugin_loader.cc"42 "common/plugin/runtime_plugin_loader.cc"
42 "common/plugin/plugin_caller.cc"43 "common/plugin/plugin_caller.cc"
@@ -0,0 +1,117 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include "common/python_runtime/ge_python_runtime_manager.h"
12+#include "common/python_runtime/ge_python_runtime_manager_helper.h"
13+ 
14+#include <dlfcn.h>
15+#include <string>
16+ 
17+#include "framework/common/debug/ge_log.h"
18+#include "graph/utils/file_utils.h"
19+ 
20+namespace ge {
21+ 
22+GePythonRuntimeManager &GePythonRuntimeManager::Instance() {
23+ static GePythonRuntimeManager instance;
24+ return instance;
25+}
26+ 
27+void GePythonRuntimeManager::AttachExistingLocked() {
28+ manager_is_owner_ = false;
29+ const char *version = g_python_api.py_get_version();
30+ GELOGI("[GePythonRuntime] Attach existing interpreter, version[%s], owner=0.", version);
31+}
32+ 
33+Status GePythonRuntimeManager::EnsureReadyLocked() {
34+ if (ready_) {
35+ return SUCCESS;
36+ }
37+ if (!ResolvePythonCApi(nullptr, false)) {
38+ if (!EnsureLibpythonLoaded(&libpython_handle_)) {
39+ GELOGE(FAILED, "[GePythonRuntime] Load libpython failed.");
40+ return FAILED;
41+ }
42+ if (!ResolvePythonCApi(libpython_handle_, true)) {
43+ GELOGE(FAILED, "[GePythonRuntime] Resolve Python C API failed after loading libpython.");
44+ ResetStateLocked();
45+ return FAILED;
46+ }
47+ }
48+ 
49+ if (g_python_api.py_is_initialized() != 0) {
50+ AttachExistingLocked();
51+ ready_ = true;
52+ return SUCCESS;
53+ }
54+ 
55+ g_python_api.py_initialize();
56+ if (g_python_api.py_eval_threads_initialized() == 0) {
57+ g_python_api.py_eval_init_threads();
58+ }
59+ ReleaseInitThreadGilLocked();
60+ manager_is_owner_ = true;
61+ ready_ = true;
62+ const char *version = g_python_api.py_get_version();
63+ GELOGI("[GePythonRuntime] Initialize owned interpreter, version[%s].", version);
64+ return SUCCESS;
65+}
66+ 
67+Status GePythonRuntimeManager::EnsureReady() {
68+ std::lock_guard<std::mutex> lock(mutex_);
69+ return EnsureReadyLocked();
70+}
71+ 
72+void GePythonRuntimeManager::ReleaseInitThreadGilLocked() {
73+ if (g_python_api.py_gil_state_check() != 0) {
74+ py_thread_state_ = g_python_api.py_eval_save_thread();
75+ GELOGI("[GePythonRuntime] Saved init thread state and released GIL.");
76+ }
77+}
78+ 
79+void GePythonRuntimeManager::ResetStateLocked() {
80+ if (libpython_handle_ != nullptr) {
81+ // GE 初始化/反初始化是进程级的,因此这里不主动 dlclose,直到进程退出时系统统一回收
82+ libpython_handle_ = nullptr;
83+ }
84+ ResetPythonCApi();
85+ py_thread_state_ = nullptr;
86+ ready_ = false;
87+ manager_is_owner_ = false;
88+}
89+ 
90+Status GePythonRuntimeManager::FinalizeOwnedInterpreterLocked() {
91+ if (!manager_is_owner_) {
92+ GELOGI("[GePythonRuntime] Skip finalize because manager is not interpreter owner.");
93+ ResetStateLocked();
94+ return SUCCESS;
95+ }
96+ if (g_python_api.py_is_initialized() == 0) {
97+ GELOGI("[GePythonRuntime] Skip finalize because interpreter is not initialized.");
98+ ResetStateLocked();
99+ return SUCCESS;
100+ }
101+ if (py_thread_state_ != nullptr) {
102+ g_python_api.py_eval_restore_thread(py_thread_state_);
103+ py_thread_state_ = nullptr;
104+ GELOGI("[GePythonRuntime] Restored init thread state before finalize.");
105+ }
106+ g_python_api.py_finalize();
107+ ResetStateLocked();
108+ GELOGI("[GePythonRuntime] Finalize owned interpreter done.");
109+ return SUCCESS;
110+}
111+ 
112+Status GePythonRuntimeManager::ShutdownProcess() {
113+ std::lock_guard<std::mutex> lock(mutex_);
114+ return FinalizeOwnedInterpreterLocked();
115+}
116+ 
117+} // namespace ge
@@ -0,0 +1,45 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#ifndef BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_H_
12+#define BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_H_
13+ 
14+#include <mutex>
15+ 
16+#include "ge/ge_api_error_codes.h"
17+ 
18+namespace ge {
19+ 
20+class GePythonRuntimeManager {
21+ public:
22+ static GePythonRuntimeManager &Instance();
23+ 
24+ Status EnsureReady();
25+ Status ShutdownProcess();
26+ 
27+ private:
28+ GePythonRuntimeManager() = default;
29+ 
30+ Status EnsureReadyLocked();
31+ void AttachExistingLocked();
32+ void ReleaseInitThreadGilLocked();
33+ void ResetStateLocked();
34+ Status FinalizeOwnedInterpreterLocked();
35+ 
36+ mutable std::mutex mutex_;
37+ bool ready_{false};
38+ bool manager_is_owner_{false};
39+ void *libpython_handle_{nullptr};
40+ void *py_thread_state_{nullptr};
41+};
42+ 
43+} // namespace ge
44+ 
45+#endif // BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_H_
@@ -0,0 +1,223 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#ifndef BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_HELPER_H_
12+#define BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_HELPER_H_
13+ 
14+#include <dlfcn.h>
15+#include <string>
16+ 
17+#include "framework/common/debug/ge_log.h"
18+#include "ge/ge_api_error_codes.h"
19+#include "graph/utils/file_utils.h"
20+ 
21+namespace ge {
22+ 
23+using PyIsInitializedFn = int (*)();
24+using PyInitializeFn = void (*)();
25+using PyFinalizeFn = void (*)();
26+using PyGetVersionFn = const char *(*)();
27+using PyEvalInitThreadsFn = void (*)();
28+using PyEvalThreadsInitializedFn = int (*)();
29+using PyEvalSaveThreadFn = void *(*)();
30+using PyEvalRestoreThreadFn = void (*)(void *);
31+using PyGILStateCheckFn = int (*)();
32+ 
33+struct PythonCApi {
34+ PyIsInitializedFn py_is_initialized{nullptr};
35+ PyInitializeFn py_initialize{nullptr};
36+ PyFinalizeFn py_finalize{nullptr};
37+ PyGetVersionFn py_get_version{nullptr};
38+ PyEvalInitThreadsFn py_eval_init_threads{nullptr};
39+ PyEvalThreadsInitializedFn py_eval_threads_initialized{nullptr};
40+ PyEvalSaveThreadFn py_eval_save_thread{nullptr};
41+ PyEvalRestoreThreadFn py_eval_restore_thread{nullptr};
42+ PyGILStateCheckFn py_gil_state_check{nullptr};
43+};
44+ 
45+struct PythonProbeResult {
46+ std::string python_command;
47+ std::string python_tag;
48+ std::string libpython_path;
49+};
50+ 
51+constexpr const char *kPyIsInitializedSymbol = "Py_IsInitialized";
52+constexpr const char *kPyInitializeSymbol = "Py_Initialize";
53+constexpr const char *kPyFinalizeSymbol = "Py_Finalize";
54+constexpr const char *kPyGetVersionSymbol = "Py_GetVersion";
55+constexpr const char *kPyEvalInitThreadsSymbol = "PyEval_InitThreads";
56+constexpr const char *kPyEvalThreadsInitializedSymbol = "PyEval_ThreadsInitialized";
57+constexpr const char *kPyEvalSaveThreadSymbol = "PyEval_SaveThread";
58+constexpr const char *kPyEvalRestoreThreadSymbol = "PyEval_RestoreThread";
59+constexpr const char *kPyGILStateCheckSymbol = "PyGILState_Check";
60+constexpr const char *kPythonRuntimeProbeScript =
61+ " -c \"import sys; print('cp%d%d' % sys.version_info[:2])\" 2>/dev/null";
62+constexpr const char *kLibpythonProbeScript =
63+ " -c \"import os, sysconfig\n"
64+ "version = sysconfig.get_config_var('VERSION') or ''\n"
65+ "libdir = sysconfig.get_config_var('LIBDIR') or ''\n"
66+ "candidates = [sysconfig.get_config_var('LDLIBRARY'), sysconfig.get_config_var('INSTSONAME'), "
67+ "sysconfig.get_config_var('LIBRARY')]\n"
68+ "candidates.extend([('libpython%s.so.1.0' % version) if version else '', "
69+ "('libpython%s.so' % version) if version else ''])\n"
70+ "seen = []\n"
71+ "for item in candidates:\n"
72+ " if item and item not in seen:\n"
73+ " seen.append(item)\n"
74+ "for item in seen:\n"
75+ " if '.so' not in item:\n"
76+ " continue\n"
77+ " path = os.path.join(libdir, item) if libdir else ''\n"
78+ " if path and os.path.exists(path):\n"
79+ " print(path)\n"
80+ " break\" 2>/dev/null";
81+constexpr int kOpenFlags = RTLD_NOW | RTLD_GLOBAL;
82+ 
83+inline PythonCApi g_python_api;
84+ 
85+#define GE_BIND_PY_SYMBOL(func_field, py_symbol) \
86+ do { \
87+ resolved.func_field = reinterpret_cast<decltype(resolved.func_field)>(dlsym(handle, py_symbol)); \
88+ if (resolved.func_field == nullptr) { \
89+ if (log_failure) { \
90+ GELOGW("[GePythonRuntime] Failed to dlsym python symbol[%s].", py_symbol); \
91+ } \
92+ return false; \
93+ } \
94+ } while (0)
95+ 
96+inline bool ResolvePythonCApi(void *libpython_handle, const bool log_failure) {
97+ void *handle = (libpython_handle != nullptr) ? libpython_handle : RTLD_DEFAULT;
98+ PythonCApi resolved;
99+ GE_BIND_PY_SYMBOL(py_is_initialized, kPyIsInitializedSymbol);
100+ GE_BIND_PY_SYMBOL(py_initialize, kPyInitializeSymbol);
101+ GE_BIND_PY_SYMBOL(py_finalize, kPyFinalizeSymbol);
102+ GE_BIND_PY_SYMBOL(py_get_version, kPyGetVersionSymbol);
103+ GE_BIND_PY_SYMBOL(py_eval_init_threads, kPyEvalInitThreadsSymbol);
104+ GE_BIND_PY_SYMBOL(py_eval_threads_initialized, kPyEvalThreadsInitializedSymbol);
105+ GE_BIND_PY_SYMBOL(py_eval_save_thread, kPyEvalSaveThreadSymbol);
106+ GE_BIND_PY_SYMBOL(py_eval_restore_thread, kPyEvalRestoreThreadSymbol);
107+ GE_BIND_PY_SYMBOL(py_gil_state_check, kPyGILStateCheckSymbol);
108+ g_python_api = resolved;
109+ return true;
110+}
111+ 
112+#undef GE_BIND_PY_SYMBOL
113+ 
114+inline void ResetPythonCApi() {
115+ g_python_api = PythonCApi {};
116+}
117+ 
118+inline std::string FirstLine(const std::string &text) {
119+ const auto pos = text.find('\n');
120+ if (pos == std::string::npos) {
121+ return text;
122+ }
123+ return text.substr(0U, pos);
124+}
125+ 
126+inline bool ReadCommandOutput(const std::string &command, std::string &output) {
127+ FILE *fp = popen(command.c_str(), "r");
128+ if (fp == nullptr) {
129+ return false;
130+ }
131+ char buffer[256] = {0};
132+ while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
133+ output += buffer;
134+ }
135+ const auto ret = pclose(fp);
136+ return (ret == 0) && (!output.empty());
137+}
138+ 
139+inline bool ProbePythonRuntimeFromCommand(const char *python_command, PythonProbeResult &result) {
140+ if ((python_command == nullptr) || (python_command[0] == '\0')) {
141+ return false;
142+ }
143+ std::string output;
144+ if (!ReadCommandOutput(std::string(python_command) + kPythonRuntimeProbeScript, output)) {
145+ return false;
146+ }
147+ const auto python_tag = FirstLine(output);
148+ if (python_tag.empty()) {
149+ return false;
150+ }
151+ result.python_command = python_command;
152+ result.python_tag = python_tag;
153+ return true;
154+}
155+ 
156+inline std::string ResolveLibpythonPathFromCommand(const std::string &python_command) {
157+ if (python_command.empty()) {
158+ return "";
159+ }
160+ std::string output;
161+ if (!ReadCommandOutput(python_command + kLibpythonProbeScript, output)) {
162+ return "";
163+ }
164+ const auto libpython_path = FirstLine(output);
165+ if (libpython_path.empty()) {
166+ return "";
167+ }
168+ const auto real_path = RealPath(libpython_path.c_str());
169+ return real_path.empty() ? libpython_path : real_path;
170+}
171+ 
172+inline bool ProbeRuntimeCandidate(const char *candidate, PythonProbeResult &probed) {
173+ if (!ProbePythonRuntimeFromCommand(candidate, probed)) {
174+ return false;
175+ }
176+ probed.libpython_path = ResolveLibpythonPathFromCommand(probed.python_command);
177+ if (probed.libpython_path.empty()) {
178+ GELOGW("[GePythonRuntime] Skip python command[%s] because libpython path is unresolved.",
179+ probed.python_command.c_str());
180+ return false;
181+ }
182+ return true;
183+}
184+ 
185+inline bool EnsureLibpythonLoaded(void **handle) {
186+ if (handle == nullptr) {
187+ return false;
188+ }
189+ if (*handle != nullptr) {
190+ return true;
191+ }
192+ 
193+ bool has_probe_result = false;
194+ for (const char *candidate : {"python3", "python"}) {
195+ PythonProbeResult probe_result;
196+ if (!ProbeRuntimeCandidate(candidate, probe_result)) {
197+ continue;
198+ }
199+ has_probe_result = true;
200+ void *opened_handle = dlopen(probe_result.libpython_path.c_str(), kOpenFlags);
201+ if (opened_handle == nullptr) {
202+ const char *open_error = dlerror();
203+ GELOGW("[GePythonRuntime] dlopen libpython[%s] failed: %s, try next candidate.",
204+ probe_result.libpython_path.c_str(), open_error == nullptr ? "" : open_error);
205+ continue;
206+ }
207+ *handle = opened_handle;
208+ GELOGI("[GePythonRuntime] Loaded libpython[%s] for python tag[%s].", probe_result.libpython_path.c_str(),
209+ probe_result.python_tag.c_str());
210+ return true;
211+ }
212+ 
213+ if (!has_probe_result) {
214+ GELOGE(FAILED, "[GePythonRuntime] Probe target python runtime failed.");
215+ return false;
216+ }
217+ GELOGE(FAILED, "[GePythonRuntime] Load libpython failed for all probed python runtime candidates.");
218+ return false;
219+}
220+ 
221+} // namespace ge
222+ 
223+#endif // BASE_COMMON_PYTHON_RUNTIME_GE_PYTHON_RUNTIME_MANAGER_HELPER_H_
@@ -60,6 +60,7 @@
60#include "analyzer/analyzer.h"60#include "analyzer/analyzer.h"
61#include "graph/utils/type_utils.h"61#include "graph/utils/type_utils.h"
62#include "graph/fusion/pass/pass_plugin_loader.h"62#include "graph/fusion/pass/pass_plugin_loader.h"
63+#include "common/python_runtime/ge_python_runtime_manager.h"
63#include "graph/operator_factory_impl.h"64#include "graph/operator_factory_impl.h"
64#include "base/err_msg.h"65#include "base/err_msg.h"
65#include "base/err_mgr.h"66#include "base/err_mgr.h"
@@ -440,6 +441,8 @@ static graphStatus aclgrphBuildInitializeImpl(std::map<std::string, std::string>
440 ge::PrintOptionMap(global_options, "global option");441 ge::PrintOptionMap(global_options, "global option");
441 GE_ASSERT_GRAPH_SUCCESS(OpLibRegistry::GetInstance().PreProcessForCustomOp());442 GE_ASSERT_GRAPH_SUCCESS(OpLibRegistry::GetInstance().PreProcessForCustomOp());
442 LoadOpsProto();443 LoadOpsProto();
444+ GE_ASSERT_SUCCESS(GePythonRuntimeManager::Instance().EnsureReady());
445+ GE_DISMISSABLE_GUARD(release_python_runtime, []() { (void)GePythonRuntimeManager::Instance().ShutdownProcess(); });
443 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());446 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());
444 447 
445 std::shared_ptr<ge::GELib> instance_ptr = ge::GELib::GetInstance();448 std::shared_ptr<ge::GELib> instance_ptr = ge::GELib::GetInstance();
@@ -457,6 +460,7 @@ static graphStatus aclgrphBuildInitializeImpl(std::map<std::string, std::string>
457 GELOGW("gelib has been initialized!");460 GELOGW("gelib has been initialized!");
458 Status ret = static_cast<uint32_t>(error_message::ErrMgrInit(error_message::ErrorMessageMode::INTERNAL_MODE));461 Status ret = static_cast<uint32_t>(error_message::ErrMgrInit(error_message::ErrorMessageMode::INTERNAL_MODE));
459 GE_ASSERT_SUCCESS(ret, "ErrorManager init failed!");462 GE_ASSERT_SUCCESS(ret, "ErrorManager init failed!");
463+ GE_DISMISS_GUARD(release_python_runtime);
460 return GRAPH_SUCCESS;464 return GRAPH_SUCCESS;
461}465}
462 466 
@@ -483,9 +487,10 @@ void aclgrphBuildFinalize() {
483 (void)fusion::ShutdownPassPluginsForProcess();487 (void)fusion::ShutdownPassPluginsForProcess();
484 if (ge::GELib::GetInstance() != nullptr && ge::GELib::GetInstance()->InitFlag()) {488 if (ge::GELib::GetInstance() != nullptr && ge::GELib::GetInstance()->InitFlag()) {
485 (void)ge::GELib::GetInstance()->Finalize();489 (void)ge::GELib::GetInstance()->Finalize();
486- return;490+ } else {
491+ GELOGW("[Notice] gelib has not been initialized!do nothing!");
487 }492 }
488- GELOGW("[Notice] gelib has not been initialized!do nothing!");493+ (void)GePythonRuntimeManager::Instance().ShutdownProcess();
489}494}
490 495 
491class Impl {496class Impl {
@@ -52,6 +52,7 @@
52#include "common/checker.h"52#include "common/checker.h"
53#include "graph/utils/op_type_utils.h"53#include "graph/utils/op_type_utils.h"
54#include "graph/fusion/pass/pass_plugin_loader.h"54#include "graph/fusion/pass/pass_plugin_loader.h"
55+#include "common/python_runtime/ge_python_runtime_manager.h"
55 56 
56namespace {57namespace {
57 58 
@@ -466,6 +467,9 @@ Status GeGenerator::Initialize(const std::map<std::string, std::string> &options
466 std::map<std::string, std::string> option_tmp;467 std::map<std::string, std::string> option_tmp;
467 option_tmp.emplace(std::pair<std::string, std::string>(string("ge.opsProtoLibPath"), opsproto_path));468 option_tmp.emplace(std::pair<std::string, std::string>(string("ge.opsProtoLibPath"), opsproto_path));
468 (void)manager->Initialize(option_tmp);469 (void)manager->Initialize(option_tmp);
470+ GE_ASSERT_SUCCESS(GePythonRuntimeManager::Instance().EnsureReady());
471+ GE_DISMISSABLE_GUARD(release_python_runtime,
472+ ([]() { (void)GePythonRuntimeManager::Instance().ShutdownProcess(); }));
469 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());473 GE_ASSERT_SUCCESS(fusion::LoadPassPlugins());
470 474 
471 ret = impl_->graph_manager_.Initialize(options);475 ret = impl_->graph_manager_.Initialize(options);
@@ -485,6 +489,7 @@ Status GeGenerator::Initialize(const std::map<std::string, std::string> &options
485 if (iter != options.end()) {489 if (iter != options.end()) {
486 impl_->build_step_ = iter->second;490 impl_->build_step_ = iter->second;
487 }491 }
492+ GE_DISMISS_GUARD(release_python_runtime);
488 return SUCCESS;493 return SUCCESS;
489}494}
490 495 
@@ -61,6 +61,7 @@ target_include_directories(helper_runtime_test PRIVATE
61target_link_options(helper_runtime_test PRIVATE61target_link_options(helper_runtime_test PRIVATE
62 -Wl,--disable-new-dtags62 -Wl,--disable-new-dtags
63 -Wl,-Bsymbolic63 -Wl,-Bsymbolic
64+ -rdynamic
64)65)
65 66 
66target_compile_options(helper_runtime_test PRIVATE67target_compile_options(helper_runtime_test PRIVATE
@@ -15,6 +15,7 @@
15#include "ge/ge_api.h"15#include "ge/ge_api.h"
16#include "ge/ge_api_v2.h"16#include "ge/ge_api_v2.h"
17#include "ge_running_env/ge_running_env_faker.h"17#include "ge_running_env/ge_running_env_faker.h"
18+#include "ge_running_env/scoped_unset_ld_preload.h"
18#include "compiler/session/dflow_api.h"19#include "compiler/session/dflow_api.h"
19namespace ge {20namespace ge {
20 21 
@@ -22,6 +23,7 @@ inline void InitGe() {
22 std::map<AscendString, AscendString> options;23 std::map<AscendString, AscendString> options;
23 options[ge::OPTION_HOST_ENV_OS] = "linux";24 options[ge::OPTION_HOST_ENV_OS] = "linux";
24 options[ge::OPTION_HOST_ENV_CPU] = "x86_64";25 options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
26+ ScopedUnsetLdPreload guard;
25 auto init_status = ge::GEInitialize(options);27 auto init_status = ge::GEInitialize(options);
26 if (init_status != SUCCESS) {28 if (init_status != SUCCESS) {
27 std::cout << "ge init failed , ret code:" << init_status << std::endl;29 std::cout << "ge init failed , ret code:" << init_status << std::endl;
@@ -41,6 +43,7 @@ inline void ReInitGe() {
41 std::map<AscendString, AscendString> options;43 std::map<AscendString, AscendString> options;
42 options[ge::OPTION_HOST_ENV_OS] = "linux";44 options[ge::OPTION_HOST_ENV_OS] = "linux";
43 options[ge::OPTION_HOST_ENV_CPU] = "x86_64";45 options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
46+ ScopedUnsetLdPreload guard;
44 auto init_status = ge::GEInitializeV2(options);47 auto init_status = ge::GEInitializeV2(options);
45 if (init_status != SUCCESS) {48 if (init_status != SUCCESS) {
46 std::cout << "ge init failed , ret code:" << init_status << std::endl;49 std::cout << "ge init failed , ret code:" << init_status << std::endl;
@@ -20,6 +20,20 @@
20using namespace std;20using namespace std;
21using namespace ge;21using namespace ge;
22 22 
23+extern "C" const char *__lsan_default_suppressions() {
24+ return "leak:_PyObject_Malloc\n"
25+ "leak:_PyObject_Realloc\n"
26+ "leak:PyType_GenericAlloc\n"
27+ "leak:PyType_Ready\n"
28+ "leak:PyObject_GC_New\n"
29+ "leak:PyObject_GC_NewVar\n"
30+ "leak:_PyObject_GC_Malloc\n"
31+ "leak:PyUnicode_New\n"
32+ "leak:Py_InitializeEx\n"
33+ "leak:PyImport_ImportModuleLevelObject\n"
34+ "leak:libpython\n";
35+}
36+ 
23int main(int argc, char **argv) {37int main(int argc, char **argv) {
24 setenv("GE_PROFILING_TO_STD_OUT", "1", true);38 setenv("GE_PROFILING_TO_STD_OUT", "1", true);
25 // Init running dir env39 // Init running dir env
@@ -227,6 +227,11 @@ class MockMmpa : public ge::MmpaStubApiGe {
227class UtestDflowApi : public testing::Test {227class UtestDflowApi : public testing::Test {
228 protected:228 protected:
229 static void SetUpTestSuite() {229 static void SetUpTestSuite() {
230+ const auto env_ptr = getenv("LD_PRELOAD");
231+ if (env_ptr != nullptr) {
232+ env = env_ptr;
233+ unsetenv("LD_PRELOAD");
234+ }
230 // Init running dir env235 // Init running dir env
231 ge::DirEnv::GetInstance().InitEngineConfJson();236 ge::DirEnv::GetInstance().InitEngineConfJson();
232 const std::map<AscendString, AscendString> options{};237 const std::map<AscendString, AscendString> options{};
@@ -239,6 +244,9 @@ class UtestDflowApi : public testing::Test {
239 static void TearDownTestSuite() {244 static void TearDownTestSuite() {
240 ge::GEFinalizeV2();245 ge::GEFinalizeV2();
241 unsetenv("RESOURCE_CONFIG_PATH");246 unsetenv("RESOURCE_CONFIG_PATH");
247+ if (!env.empty()) {
248+ setenv("LD_PRELOAD", env.c_str(), 1);
249+ }
242 }250 }
243 251 
244 void SetUp() override {252 void SetUp() override {
@@ -278,8 +286,12 @@ class UtestDflowApi : public testing::Test {
278 ge::ExecutionRuntime::SetExecutionRuntime(nullptr);286 ge::ExecutionRuntime::SetExecutionRuntime(nullptr);
279 ge::OpsKernelBuilderRegistry::GetInstance().UnregisterAll();287 ge::OpsKernelBuilderRegistry::GetInstance().UnregisterAll();
280 }288 }
289+ 
290+ static std::string env;
281};291};
282 292 
293+std::string UtestDflowApi::env;
294+ 
283TEST_F(UtestDflowApi, DFlowInitialize) {295TEST_F(UtestDflowApi, DFlowInitialize) {
284 std::map<AscendString, AscendString> options = {};296 std::map<AscendString, AscendString> options = {};
285 std::string empty_key = "";297 std::string empty_key = "";
@@ -98,6 +98,11 @@ class GeFakeOpsKernelBuilder : public OpsKernelBuilder {
98class UtestGeApiDflow : public testing::Test {98class UtestGeApiDflow : public testing::Test {
99 protected:99 protected:
100 static void SetUpTestSuite() {100 static void SetUpTestSuite() {
101+ const auto env_ptr = getenv("LD_PRELOAD");
102+ if (env_ptr != nullptr) {
103+ suite_env = env_ptr;
104+ unsetenv("LD_PRELOAD");
105+ }
101 // Init running dir env106 // Init running dir env
102 ge::DirEnv::GetInstance().InitEngineConfJson();107 ge::DirEnv::GetInstance().InitEngineConfJson();
103 const std::map<AscendString, AscendString> options{};108 const std::map<AscendString, AscendString> options{};
@@ -109,6 +114,9 @@ class UtestGeApiDflow : public testing::Test {
109 static void TearDownTestSuite() {114 static void TearDownTestSuite() {
110 ge::GEFinalizeV2();115 ge::GEFinalizeV2();
111 unsetenv("RESOURCE_CONFIG_PATH");116 unsetenv("RESOURCE_CONFIG_PATH");
117+ if (!suite_env.empty()) {
118+ setenv("LD_PRELOAD", suite_env.c_str(), 1);
119+ }
112 }120 }
113 121 
114 void SetUp() override {122 void SetUp() override {
@@ -137,8 +145,11 @@ class UtestGeApiDflow : public testing::Test {
137 }145 }
138 146 
139 std::string env;147 std::string env;
148+ static std::string suite_env;
140};149};
141 150 
151+std::string UtestGeApiDflow::suite_env;
152+ 
142TEST_F(UtestGeApiDflow, Feed_test_not_init) {153TEST_F(UtestGeApiDflow, Feed_test_not_init) {
143 std::map<std::string, std::string> options;154 std::map<std::string, std::string> options;
144 Session session(options);155 Session session(options);
@@ -172,6 +172,8 @@ target_compile_definitions(ut_libge_helper_utest PRIVATE
172target_link_options(ut_libge_helper_utest PRIVATE172target_link_options(ut_libge_helper_utest PRIVATE
173 -Wl,--disable-new-dtags173 -Wl,--disable-new-dtags
174 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}174 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}
175+ -rdynamic
176+ -Wl,-Bsymbolic
175)177)
176 178 
177target_link_libraries(ut_libge_helper_utest179target_link_libraries(ut_libge_helper_utest
@@ -15,6 +15,18 @@
15using namespace std;15using namespace std;
16using namespace ge;16using namespace ge;
17 17 
18+extern "C" const char *__lsan_default_suppressions() {
19+ return "leak:_PyObject_Malloc\n"
20+ "leak:_PyObject_Realloc\n"
21+ "leak:PyType_GenericAlloc\n"
22+ "leak:PyType_Ready\n"
23+ "leak:PyObject_GC_New\n"
24+ "leak:PyObject_GC_NewVar\n"
25+ "leak:_PyObject_GC_Malloc\n"
26+ "leak:PyUnicode_New\n"
27+ "leak:libpython\n";
28+}
29+ 
18int main(int argc, char **argv) {30int main(int argc, char **argv) {
19 // init the logging31 // init the logging
20 testing::InitGoogleTest(&argc, argv);32 testing::InitGoogleTest(&argc, argv);
@@ -0,0 +1,39 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#ifndef GE_RUNNING_ENV_SCOPED_UNSET_LD_PRELOAD_H_
12+#define GE_RUNNING_ENV_SCOPED_UNSET_LD_PRELOAD_H_
13+ 
14+#include <cstdlib>
15+#include <string>
16+ 
17+class ScopedUnsetLdPreload {
18+ public:
19+ ScopedUnsetLdPreload() {
20+ const char *ld_preload = std::getenv("LD_PRELOAD");
21+ if (ld_preload != nullptr) {
22+ has_ld_preload_ = true;
23+ ld_preload_ = ld_preload;
24+ (void)unsetenv("LD_PRELOAD");
25+ }
26+ }
27+ 
28+ ~ScopedUnsetLdPreload() {
29+ if (has_ld_preload_) {
30+ (void)setenv("LD_PRELOAD", ld_preload_.c_str(), 1);
31+ }
32+ }
33+ 
34+ private:
35+ bool has_ld_preload_{false};
36+ std::string ld_preload_;
37+};
38+ 
39+#endif // GE_RUNNING_ENV_SCOPED_UNSET_LD_PRELOAD_H_
@@ -23,6 +23,8 @@ target_compile_options(ge_running_env_test PRIVATE
23 23 
24target_link_options(ge_running_env_test PRIVATE24target_link_options(ge_running_env_test PRIVATE
25 -Wl,--disable-new-dtags25 -Wl,--disable-new-dtags
26+ -rdynamic
27+ -Wl,-Bsymbolic
26)28)
27 29 
28target_link_libraries(ge_running_env_test PUBLIC intf_llt_pub GTestShared::gtest ge_running_env ge_common_base30target_link_libraries(ge_running_env_test PUBLIC intf_llt_pub GTestShared::gtest ge_running_env ge_common_base
@@ -13,14 +13,30 @@
13#include "common/debug/log.h"13#include "common/debug/log.h"
14#include "ge/ge_api.h"14#include "ge/ge_api.h"
15#include "ge_running_env/ge_running_env_faker.h"15#include "ge_running_env/ge_running_env_faker.h"
16+#include "ge_running_env/scoped_unset_ld_preload.h"
16 17 
17using namespace std;18using namespace std;
18using namespace ge;19using namespace ge;
19 20 
21+extern "C" const char *__lsan_default_suppressions() {
22+ return "leak:_PyObject_Malloc\n"
23+ "leak:_PyObject_Realloc\n"
24+ "leak:PyType_GenericAlloc\n"
25+ "leak:PyType_Ready\n"
26+ "leak:PyObject_GC_New\n"
27+ "leak:PyObject_GC_NewVar\n"
28+ "leak:_PyObject_GC_Malloc\n"
29+ "leak:PyUnicode_New\n"
30+ "leak:Py_InitializeEx\n"
31+ "leak:PyImport_ImportModuleLevelObject\n"
32+ "leak:libpython\n";
33+}
34+ 
20int main(int argc, char **argv) {35int main(int argc, char **argv) {
21 map<AscendString, AscendString> options;36 map<AscendString, AscendString> options;
22 options.insert({AscendString("ge.exec.opWaitTimeout"), AscendString("11")});37 options.insert({AscendString("ge.exec.opWaitTimeout"), AscendString("11")});
23 options.insert({AscendString("ge.exec.opExecuteTimeout"), AscendString("11")});38 options.insert({AscendString("ge.exec.opExecuteTimeout"), AscendString("11")});
39+ ScopedUnsetLdPreload guard;
24 ge::GEInitialize(options);40 ge::GEInitialize(options);
25 GeRunningEnvFaker::BackupEnv();41 GeRunningEnvFaker::BackupEnv();
26 testing::InitGoogleTest(&argc, argv);42 testing::InitGoogleTest(&argc, argv);
@@ -138,6 +138,8 @@ target_include_directories(graph_engine_test PRIVATE
138 138 
139target_link_options(graph_engine_test PRIVATE139target_link_options(graph_engine_test PRIVATE
140 -Wl,--disable-new-dtags140 -Wl,--disable-new-dtags
141+ -rdynamic
142+ -Wl,-Bsymbolic
141)143)
142 144 
143target_link_libraries(graph_engine_test145target_link_libraries(graph_engine_test
@@ -226,6 +228,8 @@ target_include_directories(ge_common_atc PRIVATE
226 228 
227target_link_options(ge_common_atc PRIVATE229target_link_options(ge_common_atc PRIVATE
228 -Wl,--disable-new-dtags230 -Wl,--disable-new-dtags
231+ -rdynamic
232+ -Wl,-Bsymbolic
229 )233 )
230 234 
231target_link_libraries(ge_common_atc235target_link_libraries(ge_common_atc
@@ -401,6 +405,7 @@ target_link_options(graph_engine_compile_test PRIVATE
401 -Wl,--disable-new-dtags405 -Wl,--disable-new-dtags
402 -Wl,-rpath,${CMAKE_BINARY_DIR}/compiler406 -Wl,-rpath,${CMAKE_BINARY_DIR}/compiler
403 -rdynamic407 -rdynamic
408+ -Wl,-Bsymbolic
404)409)
405target_link_libraries(graph_engine_compile_test410target_link_libraries(graph_engine_compile_test
406 intf_llt_pub411 intf_llt_pub
@@ -20,6 +20,7 @@
20#include <gtest/gtest.h>20#include <gtest/gtest.h>
21#include "framework/ge_runtime_stub/include/common/dump_checker.h" // DumpCheckRuntimeStub21#include "framework/ge_runtime_stub/include/common/dump_checker.h" // DumpCheckRuntimeStub
22#include "ge_running_env/ge_running_env_faker.h" // GeRunningEnvFaker22#include "ge_running_env/ge_running_env_faker.h" // GeRunningEnvFaker
23+#include "ge_running_env/scoped_unset_ld_preload.h" // GeRunningEnvFaker
23#include "ge/st/stubs/utils/mock_ops_kernel_builder.h" // MockForGenerateTask24#include "ge/st/stubs/utils/mock_ops_kernel_builder.h" // MockForGenerateTask
24#include "ge/st/stubs/utils/taskdef_builder.h" // AiCoreTaskDefBuilder25#include "ge/st/stubs/utils/taskdef_builder.h" // AiCoreTaskDefBuilder
25#include "common/opskernel/ops_kernel_info_types.h"26#include "common/opskernel/ops_kernel_info_types.h"
@@ -57,6 +58,7 @@ template <bool dynamic>
57class DumpST : public ::testing::Test {58class DumpST : public ::testing::Test {
58 public:59 public:
59 static void SetUpTestSuite() {60 static void SetUpTestSuite() {
61+ ScopedUnsetLdPreload guard;
60 const std::map<AscendString, AscendString> options = {62 const std::map<AscendString, AscendString> options = {
61 {OPTION_HOST_ENV_OS, "linux"},63 {OPTION_HOST_ENV_OS, "linux"},
62 {OPTION_HOST_ENV_CPU, "x86_64"},64 {OPTION_HOST_ENV_CPU, "x86_64"},
@@ -14,6 +14,20 @@
14using namespace std;14using namespace std;
15using namespace ge;15using namespace ge;
16 16 
17+extern "C" const char *__lsan_default_suppressions() {
18+ return "leak:_PyObject_Malloc\n"
19+ "leak:_PyObject_Realloc\n"
20+ "leak:PyType_GenericAlloc\n"
21+ "leak:PyType_Ready\n"
22+ "leak:PyObject_GC_New\n"
23+ "leak:PyObject_GC_NewVar\n"
24+ "leak:_PyObject_GC_Malloc\n"
25+ "leak:PyUnicode_New\n"
26+ "leak:Py_InitializeEx\n"
27+ "leak:PyImport_ImportModuleLevelObject\n"
28+ "leak:libpython\n";
29+}
30+ 
17int main(int argc, char **argv) {31int main(int argc, char **argv) {
18 gert::LoadDefaultSpaceRegistry();32 gert::LoadDefaultSpaceRegistry();
19 testing::InitGoogleTest(&argc, argv);33 testing::InitGoogleTest(&argc, argv);
@@ -20,6 +20,25 @@
20using namespace std;20using namespace std;
21using namespace ge;21using namespace ge;
22 22 
23+extern "C" const char *__lsan_default_suppressions() {
24+ return "leak:_PyObject_Malloc\n"
25+ "leak:_PyObject_Realloc\n"
26+ "leak:PyType_GenericAlloc\n"
27+ "leak:PyType_Ready\n"
28+ "leak:PyObject_GC_New\n"
29+ "leak:PyObject_GC_NewVar\n"
30+ "leak:_PyObject_GC_Malloc\n"
31+ "leak:PyUnicode_New\n"
32+ "leak:Py_InitializeEx\n"
33+ "leak:PyImport_ImportModuleLevelObject\n"
34+ "leak:PyThread_allocate_lock\n"
35+ "leak:pybind11::detail::make_static_property_type\n"
36+ "leak:pybind11::detail::make_object_base_type\n"
37+ "leak:pybind11::detail::get_internals\n"
38+ "leak:pybind11::detail::get_local_internals\n"
39+ "leak:libpython\n";
40+}
41+ 
23int main(int argc, char **argv) {42int main(int argc, char **argv) {
24 setenv("GE_PROFILING_TO_STD_OUT", "1", true);43 setenv("GE_PROFILING_TO_STD_OUT", "1", true);
25 // Init running dir env44 // Init running dir env
@@ -384,6 +384,7 @@ set(BASE_COMMON_TEST_FILES
384 "common/properties_manager_unittest.cc"384 "common/properties_manager_unittest.cc"
385 "common/kernel_store_unittest.cc"385 "common/kernel_store_unittest.cc"
386 "common/ge_auth_file_saver_unittest.cc"386 "common/ge_auth_file_saver_unittest.cc"
387+ "common/ge_python_runtime_unittest.cc"
387 "common/tbe_plugin_manager_unittest.cc"388 "common/tbe_plugin_manager_unittest.cc"
388 "common/file_constant_unittest.cc"389 "common/file_constant_unittest.cc"
389 "common/graph_compile_summary_impl_unittest.cc"390 "common/graph_compile_summary_impl_unittest.cc"
@@ -713,6 +714,8 @@ target_include_directories(ut_libge_multiparts_utest PRIVATE
713target_link_options(ut_libge_multiparts_utest PRIVATE714target_link_options(ut_libge_multiparts_utest PRIVATE
714 -Wl,--disable-new-dtags715 -Wl,--disable-new-dtags
715 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}716 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}
717+ -rdynamic
718+ -Wl,-Bsymbolic
716)719)
717 720 
718target_link_libraries(ut_libge_multiparts_utest721target_link_libraries(ut_libge_multiparts_utest
@@ -924,6 +927,8 @@ target_link_options(ut_libge_others_utest PRIVATE
924 -Wl,--disable-new-dtags927 -Wl,--disable-new-dtags
925 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}928 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}
926 -Wl,-rpath,${CMAKE_BINARY_DIR}/compiler929 -Wl,-rpath,${CMAKE_BINARY_DIR}/compiler
930+ -rdynamic
931+ -Wl,-Bsymbolic
927)932)
928 933 
929target_link_libraries(ut_libge_others_utest934target_link_libraries(ut_libge_others_utest
@@ -979,6 +984,7 @@ target_link_libraries(ut_python_pass_artifact_selector_utest
979 ge_common_base984 ge_common_base
980 opp_registry985 opp_registry
981 register986 register
987+ unified_dlog
982)988)
983 989 
984target_link_options(ut_python_pass_artifact_selector_utest PRIVATE990target_link_options(ut_python_pass_artifact_selector_utest PRIVATE
@@ -1167,6 +1173,8 @@ target_include_directories(ut_libge_label_maker_utest PRIVATE
1167target_link_options(ut_libge_label_maker_utest PRIVATE1173target_link_options(ut_libge_label_maker_utest PRIVATE
1168 -Wl,--disable-new-dtags1174 -Wl,--disable-new-dtags
1169 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}1175 -Wl,-rpath,${CMAKE_CURRENT_LIST_DIR}
1176+ -rdynamic
1177+ -Wl,-Bsymbolic
1170)1178)
1171 1179 
1172# TODO:ge_ut_common need shrink; it has too many depends so1180# TODO:ge_ut_common need shrink; it has too many depends so
@@ -0,0 +1,215 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <gtest/gtest.h>
12+ 
13+#include "common/python_runtime/ge_python_runtime_manager.h"
14+#include "common/python_runtime/ge_python_runtime_manager_helper.h"
15+ 
16+namespace ge {
17+namespace {
18+int g_py_initialized = 0;
19+int g_threads_initialized = 0;
20+int g_py_initialize_count = 0;
21+int g_py_finalize_count = 0;
22+int g_py_eval_init_threads_count = 0;
23+int g_py_eval_save_thread_count = 0;
24+int g_py_eval_restore_thread_count = 0;
25+int g_py_gil_state_check = 0;
26+ 
27+int FakePyIsInitialized() {
28+ return g_py_initialized;
29+}
30+ 
31+void FakePyInitialize() {
32+ ++g_py_initialize_count;
33+ g_py_initialized = 1;
34+}
35+ 
36+void FakePyFinalize() {
37+ ++g_py_finalize_count;
38+ g_py_initialized = 0;
39+}
40+ 
41+const char *FakePyGetVersion() {
42+ return "3.13.0";
43+}
44+ 
45+void FakePyEvalInitThreads() {
46+ ++g_py_eval_init_threads_count;
47+ g_threads_initialized = 1;
48+}
49+ 
50+int FakePyEvalThreadsInitialized() {
51+ return g_threads_initialized;
52+}
53+ 
54+void *FakePyEvalSaveThread() {
55+ ++g_py_eval_save_thread_count;
56+ return reinterpret_cast<void *>(0x100);
57+}
58+ 
59+void FakePyEvalRestoreThread(void *thread_state) {
60+ (void)thread_state;
61+ ++g_py_eval_restore_thread_count;
62+}
63+ 
64+int FakePyGILStateCheck() {
65+ return g_py_gil_state_check;
66+}
67+ 
68+extern "C" int Py_IsInitialized() {
69+ return FakePyIsInitialized();
70+}
71+ 
72+extern "C" void Py_Initialize() {
73+ FakePyInitialize();
74+}
75+ 
76+extern "C" void Py_Finalize() {
77+ FakePyFinalize();
78+}
79+ 
80+extern "C" const char *Py_GetVersion() {
81+ return FakePyGetVersion();
82+}
83+ 
84+extern "C" void PyEval_InitThreads() {
85+ FakePyEvalInitThreads();
86+}
87+ 
88+extern "C" int PyEval_ThreadsInitialized() {
89+ return FakePyEvalThreadsInitialized();
90+}
91+ 
92+extern "C" void *PyEval_SaveThread() {
93+ return FakePyEvalSaveThread();
94+}
95+ 
96+extern "C" void PyEval_RestoreThread(void *thread_state) {
97+ FakePyEvalRestoreThread(thread_state);
98+}
99+ 
100+extern "C" int PyGILState_Check() {
101+ return FakePyGILStateCheck();
102+}
103+ 
104+void ResetFakePythonState() {
105+ g_py_initialized = 0;
106+ g_threads_initialized = 0;
107+ g_py_initialize_count = 0;
108+ g_py_finalize_count = 0;
109+ g_py_eval_init_threads_count = 0;
110+ g_py_eval_save_thread_count = 0;
111+ g_py_eval_restore_thread_count = 0;
112+ g_py_gil_state_check = 0;
113+}
114+ 
115+class UtestGePythonRuntimeManager : public testing::Test {
116+ protected:
117+ void SetUp() override {
118+ auto &manager = GePythonRuntimeManager::Instance();
119+ (void)manager.ShutdownProcess();
120+ ResetFakePythonState();
121+ g_py_gil_state_check = 1;
122+ }
123+ 
124+ void TearDown() override {
125+ auto &manager = GePythonRuntimeManager::Instance();
126+ (void)manager.ShutdownProcess();
127+ ResetFakePythonState();
128+ }
129+};
130+ 
131+TEST_F(UtestGePythonRuntimeManager, EnsureReadyAttachesExistingInterpreter) {
132+ g_py_initialized = 1;
133+ 
134+ auto &manager = GePythonRuntimeManager::Instance();
135+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
136+ 
137+ EXPECT_EQ(g_py_initialize_count, 0);
138+ EXPECT_EQ(g_py_eval_init_threads_count, 0);
139+ EXPECT_EQ(g_py_eval_save_thread_count, 0);
140+ 
141+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
142+ EXPECT_EQ(g_py_finalize_count, 0);
143+ EXPECT_EQ(g_py_initialized, 1);
144+}
145+ 
146+TEST_F(UtestGePythonRuntimeManager, EnsureReadyInitializesOwnedInterpreterAndShutdownFinalizes) {
147+ auto &manager = GePythonRuntimeManager::Instance();
148+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
149+ 
150+ EXPECT_EQ(g_py_initialize_count, 1);
151+ EXPECT_EQ(g_py_eval_init_threads_count, 1);
152+ EXPECT_EQ(g_py_eval_save_thread_count, 1);
153+ 
154+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
155+ EXPECT_EQ(g_py_initialize_count, 1);
156+ EXPECT_EQ(g_py_eval_save_thread_count, 1);
157+ 
158+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
159+ EXPECT_EQ(g_py_finalize_count, 1);
160+ EXPECT_EQ(g_py_eval_restore_thread_count, 1);
161+ 
162+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
163+ EXPECT_EQ(g_py_initialize_count, 2);
164+ EXPECT_EQ(g_py_eval_save_thread_count, 2);
165+}
166+ 
167+TEST_F(UtestGePythonRuntimeManager, FinalizeOwnedInterpreterSkipsWhenNotInitialized) {
168+ auto &manager = GePythonRuntimeManager::Instance();
169+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
170+ 
171+ g_py_initialized = 0;
172+ 
173+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
174+ EXPECT_EQ(g_py_finalize_count, 0);
175+}
176+ 
177+TEST_F(UtestGePythonRuntimeManager, ShutdownProcessWhenNotReady) {
178+ auto &manager = GePythonRuntimeManager::Instance();
179+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
180+ EXPECT_EQ(g_py_finalize_count, 0);
181+}
182+ 
183+TEST_F(UtestGePythonRuntimeManager, EnsureReadyWithThreadsAlreadyInitialized) {
184+ g_py_initialized = 0;
185+ g_threads_initialized = 1;
186+ 
187+ auto &manager = GePythonRuntimeManager::Instance();
188+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
189+ 
190+ EXPECT_EQ(g_py_initialize_count, 1);
191+ EXPECT_EQ(g_py_eval_init_threads_count, 0);
192+}
193+ 
194+TEST_F(UtestGePythonRuntimeManager, EnsureReadyIdempotentAfterShutdown) {
195+ auto &manager = GePythonRuntimeManager::Instance();
196+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
197+ 
198+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
199+ 
200+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
201+ EXPECT_EQ(g_py_initialize_count, 2);
202+}
203+ 
204+TEST_F(UtestGePythonRuntimeManager, FinalizeNonOwnerPreservesInterpreterState) {
205+ g_py_initialized = 1;
206+ 
207+ auto &manager = GePythonRuntimeManager::Instance();
208+ EXPECT_EQ(manager.EnsureReady(), SUCCESS);
209+ 
210+ EXPECT_EQ(manager.ShutdownProcess(), SUCCESS);
211+ EXPECT_EQ(g_py_finalize_count, 0);
212+ EXPECT_EQ(g_py_initialized, 1);
213+}
214+} // namespace
215+} // namespace ge
@@ -390,6 +390,8 @@ void ResetPatternFusionRuntimeSnapshot() {
390 390 
391std::atomic<bool> g_force_py_is_initialized_init_failure{false};391std::atomic<bool> g_force_py_is_initialized_init_failure{false};
392std::atomic<uint32_t> g_py_is_initialized_call_count{0U};392std::atomic<uint32_t> g_py_is_initialized_call_count{0U};
393+std::atomic<bool> g_force_py_get_version_probe_failure{false};
394+constexpr const char *kProbeFailurePyVersion = "invalid-runtime";
393 395 
394int QueryRealPyIsInitializedForUt() {396int QueryRealPyIsInitializedForUt() {
395 using PyIsInitializedFn = int (*)();397 using PyIsInitializedFn = int (*)();
@@ -405,6 +407,19 @@ extern "C" int Py_IsInitialized() {
405 return QueryRealPyIsInitializedForUt();407 return QueryRealPyIsInitializedForUt();
406}408}
407 409 
410+const char *QueryRealPyGetVersionForUt() {
411+ using PyGetVersionFn = const char *(*)();
412+ auto *py_get_version = reinterpret_cast<PyGetVersionFn>(dlsym(RTLD_NEXT, "Py_GetVersion"));
413+ return (py_get_version == nullptr) ? "" : py_get_version();
414+}
415+ 
416+extern "C" const char *Py_GetVersion() {
417+ if (g_force_py_get_version_probe_failure.load(std::memory_order_acquire)) {
418+ return kProbeFailurePyVersion;
419+ }
420+ return QueryRealPyGetVersionForUt();
421+}
422+ 
408class ScopedPyIsInitializedInitFailureForUt {423class ScopedPyIsInitializedInitFailureForUt {
409 public:424 public:
410 ScopedPyIsInitializedInitFailureForUt() {425 ScopedPyIsInitializedInitFailureForUt() {
@@ -418,6 +433,21 @@ class ScopedPyIsInitializedInitFailureForUt {
418 }433 }
419};434};
420 435 
436+class ScopedPyRuntimeProbeFailureForUt {
437+ public:
438+ ScopedPyRuntimeProbeFailureForUt() {
439+ g_force_py_is_initialized_init_failure.store(true, std::memory_order_release);
440+ g_py_is_initialized_call_count.store(0U, std::memory_order_release);
441+ g_force_py_get_version_probe_failure.store(true, std::memory_order_release);
442+ }
443+ 
444+ ~ScopedPyRuntimeProbeFailureForUt() {
445+ g_force_py_get_version_probe_failure.store(false, std::memory_order_release);
446+ g_force_py_is_initialized_init_failure.store(false, std::memory_order_release);
447+ g_py_is_initialized_call_count.store(0U, std::memory_order_release);
448+ }
449+};
450+ 
421void *OpenLibraryFailedForUt(const char *path, int flags) {451void *OpenLibraryFailedForUt(const char *path, int flags) {
422 (void)path;452 (void)path;
423 (void)flags;453 (void)flags;
@@ -595,6 +625,57 @@ void ForgetNativeModuleForUt() {
595 " sys.modules.pop(name, None)\n");625 " sys.modules.pop(name, None)\n");
596}626}
597 627 
628+class ScopedLoadedPythonPassForUt {
629+ public:
630+ ~ScopedLoadedPythonPassForUt() {
631+ UnloadPythonPasses();
632+ }
633+};
634+ 
635+const std::string &GetBridgeConfigDirForUt() {
636+ static ScopedTempDir temp_dir;
637+ static const std::string dir = []() {
638+ temp_dir.MakeDir("ge/passes");
639+ WriteFile(temp_dir.CreateFilePath("ge/__init__.py"), "");
640+ WriteFile(temp_dir.CreateFilePath("ge/passes/__init__.py"),
641+ "def clear_registered_passes():\n"
642+ " pass\n");
643+ WriteFile(temp_dir.CreateFilePath("ge/passes/fake_native.py"), "configured_native_loaded = True\n");
644+ WriteFile(temp_dir.CreateFilePath("ge/passes/_bridge.py"),
645+ "def clear_pass_holders():\n"
646+ " pass\n"
647+ "\n"
648+ "def clear_loaded_pass_modules():\n"
649+ " pass\n");
650+ return temp_dir.FilePath("");
651+ }();
652+ return dir;
653+}
654+ 
655+const std::string &GetBridgeNativeModulePathForUt() {
656+ static const std::string path = GetBridgeConfigDirForUt() + "/ge/passes/fake_native.py";
657+ return path;
658+}
659+ 
660+void RestoreBridgeConfigForUt(const PythonFusionPassBridgeApi &api) {
661+ if (api.set_artifact_config == nullptr) {
662+ return;
663+ }
664+ 
665+ PythonFusionPassBridgeArtifactConfig config = {nullptr, GetBridgeNativeModulePathForUt().c_str()};
666+ (void)api.set_artifact_config(&config);
667+}
668+ 
669+void CleanupBridgeStateForUt(const PythonFusionPassBridgeApi &api) {
670+ ScopedEnvVar scoped_python_path("PYTHONPATH", GetBridgeConfigDirForUt());
671+ ScopedPythonPathForUt scoped_sys_path(GetBridgeConfigDirForUt());
672+ RestoreBridgeConfigForUt(api);
673+ if (api.reset_bridge_state != nullptr) {
674+ api.reset_bridge_state();
675+ }
676+ ForgetNativeModuleForUt();
677+}
678+ 
598int g_direct_bridge_registered_count = 0;679int g_direct_bridge_registered_count = 0;
599 680 
600bool RecordPythonPassFromDirectBridge(const PythonPassDescriptor *pass_desc,681bool RecordPythonPassFromDirectBridge(const PythonPassDescriptor *pass_desc,
@@ -709,8 +790,6 @@ class UtestFusionPassExecutor : public testing::Test {
709 void SetUp() override {790 void SetUp() override {
710 PreparePythonPathForSt();791 PreparePythonPathForSt();
711 (void)unsetenv(kEnvPythonPassPath);792 (void)unsetenv(kEnvPythonPassPath);
712- // 逐 case 只清理 Python pass 业务态,避免在同一测试进程内反复 finalize/dlclose。
713- UnloadPythonPasses();
714 PassRegistry::GetInstance().name_2_fusion_pass_regs_.clear();793 PassRegistry::GetInstance().name_2_fusion_pass_regs_.clear();
715 PassRegistry::GetInstance().descriptor_key_2_python_pass_descs_.clear();794 PassRegistry::GetInstance().descriptor_key_2_python_pass_descs_.clear();
716 PassRegistry::GetInstance().pass_name_2_python_pass_create_contexts_.clear();795 PassRegistry::GetInstance().pass_name_2_python_pass_create_contexts_.clear();
@@ -725,7 +804,6 @@ class UtestFusionPassExecutor : public testing::Test {
725 }804 }
726 void TearDown() override {805 void TearDown() override {
727 (void)unsetenv(kEnvPythonPassPath);806 (void)unsetenv(kEnvPythonPassPath);
728- UnloadPythonPasses();
729 PassRegistry::GetInstance().name_2_fusion_pass_regs_.clear();807 PassRegistry::GetInstance().name_2_fusion_pass_regs_.clear();
730 PassRegistry::GetInstance().descriptor_key_2_python_pass_descs_.clear();808 PassRegistry::GetInstance().descriptor_key_2_python_pass_descs_.clear();
731 PassRegistry::GetInstance().pass_name_2_python_pass_create_contexts_.clear();809 PassRegistry::GetInstance().pass_name_2_python_pass_create_contexts_.clear();
@@ -753,14 +831,17 @@ class UtestFusionPassExecutor : public testing::Test {
753 const std::string new_python_path = std::string(ST_FUSION_PASS_PY_INSTALL_DIR) + ":" + python_path_bak_;831 const std::string new_python_path = std::string(ST_FUSION_PASS_PY_INSTALL_DIR) + ":" + python_path_bak_;
754 (void)setenv("PYTHONPATH", new_python_path.c_str(), 1);832 (void)setenv("PYTHONPATH", new_python_path.c_str(), 1);
755 }833 }
834+ PrependPythonPathForUt(ST_FUSION_PASS_PY_INSTALL_DIR);
756 return;835 return;
757 }836 }
758 (void)setenv("PYTHONPATH", ST_FUSION_PASS_PY_INSTALL_DIR, 1);837 (void)setenv("PYTHONPATH", ST_FUSION_PASS_PY_INSTALL_DIR, 1);
838+ PrependPythonPathForUt(ST_FUSION_PASS_PY_INSTALL_DIR);
759#endif839#endif
760 }840 }
761 841 
762 void RestorePythonPathForSt() {842 void RestorePythonPathForSt() {
763#ifdef ST_FUSION_PASS_PY_INSTALL_DIR843#ifdef ST_FUSION_PASS_PY_INSTALL_DIR
844+ RemovePythonPathForUt(ST_FUSION_PASS_PY_INSTALL_DIR);
764 if (has_python_path_bak_) {845 if (has_python_path_bak_) {
765 (void)setenv("PYTHONPATH", python_path_bak_.c_str(), 1);846 (void)setenv("PYTHONPATH", python_path_bak_.c_str(), 1);
766 } else {847 } else {
@@ -1388,7 +1469,9 @@ TEST_F(UtestFusionPassExecutor, PythonPassBridgeLoader_ProbesPathPythonRuntime)
1388 ASSERT_EQ(chmod(fake_python.c_str(), 0700), 0);1469 ASSERT_EQ(chmod(fake_python.c_str(), 0700), 0);
1389 1470 
1390 ScopedEnvVar scoped_path("PATH", temp_dir.FilePath(""));1471 ScopedEnvVar scoped_path("PATH", temp_dir.FilePath(""));
1472+ ScopedPyRuntimeProbeFailureForUt scoped_probe_failure;
1391 EXPECT_EQ(RegisterPythonPassesFromPlugin(), FAILED);1473 EXPECT_EQ(RegisterPythonPassesFromPlugin(), FAILED);
1474+ ShutdownPythonPassesForProcess();
1392}1475}
1393 1476 
1394TEST_F(UtestFusionPassExecutor, PythonPassBridgeLoader_SkipsBrokenPrebuiltCandidate) {1477TEST_F(UtestFusionPassExecutor, PythonPassBridgeLoader_SkipsBrokenPrebuiltCandidate) {
@@ -1483,7 +1566,7 @@ TEST_F(UtestFusionPassExecutor, PythonPassBridgeCApi_ConfiguredNativeModulePathF
1483 g_direct_bridge_registered_count = 0;1566 g_direct_bridge_registered_count = 0;
1484 EXPECT_EQ(api->register_passes(&registrar), FAILED);1567 EXPECT_EQ(api->register_passes(&registrar), FAILED);
1485 EXPECT_EQ(g_direct_bridge_registered_count, 0);1568 EXPECT_EQ(g_direct_bridge_registered_count, 0);
1486- ForgetNativeModuleForUt();1569+ CleanupBridgeStateForUt(*api);
1487}1570}
1488 1571 
1489TEST_F(UtestFusionPassExecutor, PythonPassPybindBridge_InterpreterInitializationFailed) {1572TEST_F(UtestFusionPassExecutor, PythonPassPybindBridge_InterpreterInitializationFailed) {
@@ -1536,6 +1619,7 @@ TEST_F(UtestFusionPassExecutor, PythonPassPybindBridge_InterpreterInitialization
1536 api->reset_bridge_state();1619 api->reset_bridge_state();
1537 ForgetNativeModuleForUt();1620 ForgetNativeModuleForUt();
1538 EXPECT_EQ(g_direct_bridge_registered_count, 0);1621 EXPECT_EQ(g_direct_bridge_registered_count, 0);
1622+ CleanupBridgeStateForUt(*api);
1539}1623}
1540 1624 
1541TEST_F(UtestFusionPassExecutor, PythonPassBridgeCApi_LoadsConfiguredNativeModulePath) {1625TEST_F(UtestFusionPassExecutor, PythonPassBridgeCApi_LoadsConfiguredNativeModulePath) {
@@ -1593,7 +1677,7 @@ TEST_F(UtestFusionPassExecutor, PythonPassBridgeCApi_LoadsConfiguredNativeModule
1593 1677 
1594 api->reset_bridge_state();1678 api->reset_bridge_state();
1595 EXPECT_EQ(api->set_artifact_config(&empty_config), SUCCESS);1679 EXPECT_EQ(api->set_artifact_config(&empty_config), SUCCESS);
1596- ForgetNativeModuleForUt();1680+ CleanupBridgeStateForUt(*api);
1597}1681}
1598 1682 
1599TEST_F(UtestFusionPassExecutor, PythonFusionBasePass_PybindBridge_RunSuccess) {1683TEST_F(UtestFusionPassExecutor, PythonFusionBasePass_PybindBridge_RunSuccess) {
@@ -1603,6 +1687,7 @@ TEST_F(UtestFusionPassExecutor, PythonFusionBasePass_PybindBridge_RunSuccess) {
1603 1687 
1604 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPassFilePath());1688 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPassFilePath());
1605 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);1689 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);
1690+ ScopedLoadedPythonPassForUt loaded_python_pass;
1606 1691 
1607 auto target_compute_graph = gert::ShareGraph::BuildSingleNodeGraph();1692 auto target_compute_graph = gert::ShareGraph::BuildSingleNodeGraph();
1608 const auto expected_graph_name = target_compute_graph->GetName();1693 const auto expected_graph_name = target_compute_graph->GetName();
@@ -1616,6 +1701,7 @@ TEST_F(UtestFusionPassExecutor, PythonFusionBasePass_PybindBridge_RunFailedOnPyt
1616 EnsureSharedPybindPassFile();1701 EnsureSharedPybindPassFile();
1617 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPassFilePath());1702 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPassFilePath());
1618 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);1703 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);
1704+ ScopedLoadedPythonPassForUt loaded_python_pass;
1619 1705 
1620 auto target_compute_graph = gert::ShareGraph::BuildSingleNodeGraph();1706 auto target_compute_graph = gert::ShareGraph::BuildSingleNodeGraph();
1621 FusionPassExecutor pass_executor;1707 FusionPassExecutor pass_executor;
@@ -1629,6 +1715,7 @@ TEST_F(UtestFusionPassExecutor, PythonPatternFusionPass_PybindBridge_RunSuccess)
1629 1715 
1630 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPatternPassFilePath());1716 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPatternPassFilePath());
1631 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);1717 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);
1718+ ScopedLoadedPythonPassForUt loaded_python_pass;
1632 1719 
1633 auto target_graph = ge::es::EsGraphBuilder("python_pattern_target");1720 auto target_graph = ge::es::EsGraphBuilder("python_pattern_target");
1634 auto *esb_graph = target_graph.GetCGraphBuilder();1721 auto *esb_graph = target_graph.GetCGraphBuilder();
@@ -1666,6 +1753,7 @@ TEST_F(UtestFusionPassExecutor, PythonPatternFusionPass_PybindBridge_MatcherConf
1666 1753 
1667 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPatternMatcherConfigPassFilePath());1754 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindPatternMatcherConfigPassFilePath());
1668 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);1755 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);
1756+ ScopedLoadedPythonPassForUt loaded_python_pass;
1669 1757 
1670 auto target_graph = ge::es::EsGraphBuilder("python_pattern_matcher_config_target");1758 auto target_graph = ge::es::EsGraphBuilder("python_pattern_matcher_config_target");
1671 auto *esb_graph = target_graph.GetCGraphBuilder();1759 auto *esb_graph = target_graph.GetCGraphBuilder();
@@ -1702,6 +1790,7 @@ TEST_F(UtestFusionPassExecutor, PythonDecomposePass_PybindBridge_RunSuccess) {
1702 1790 
1703 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindDecomposePassFilePath());1791 ScopedEnvVar scoped_py_pass_path(kEnvPythonPassPath, GetSharedPybindDecomposePassFilePath());
1704 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);1792 ASSERT_EQ(RegisterPythonPassesFromPlugin(), SUCCESS);
1793+ ScopedLoadedPythonPassForUt loaded_python_pass;
1705 1794 
1706 auto target_graph = ge::es::EsGraphBuilder("python_decompose_target");1795 auto target_graph = ge::es::EsGraphBuilder("python_decompose_target");
1707 auto *esb_graph = target_graph.GetCGraphBuilder();1796 auto *esb_graph = target_graph.GetCGraphBuilder();
@@ -1990,25 +2079,3 @@ TEST_F(UtestFusionPassExecutor, RunPasses_SkipOrphanSubgraph) {
1990}2079}
1991} // namespace fusion2080} // namespace fusion
1992} // namespace ge2081} // namespace ge
1993- 
1994-// CPython 内部分配器(_PyObject_Malloc / PyThread_allocate_lock)在 Py_Finalize()
1995-// 后仍有残余内存不被回收,这是 CPython 的已知行为,不是业务代码的泄漏。
1996-// pybind11 的内部类型对象(make_static_property_type / make_object_base_type)
1997-// 在 get_internals() 中创建,在解释器关闭时也不会被释放,这是 pybind11 的已知行为。
1998-// _ge_pass_native.so 中的 pybind11 绑定在模块卸载时的少量残余内存是 Python C 扩展的已知行为。
1999-// 通过 LSan 抑制规则让 ut_fusion_pass_executor_utest 不因此失败。
2000-extern "C" const char *__lsan_default_suppressions() {
2001- return "leak:_PyObject_Malloc\n"
2002- "leak:PyThread_allocate_lock\n"
2003- "leak:_PyObject_Realloc\n"
2004- "leak:PyType_GenericAlloc\n"
2005- "leak:PyType_Ready\n"
2006- "leak:PyObject_GC_New\n"
2007- "leak:PyObject_GC_NewVar\n"
2008- "leak:_PyObject_GC_Malloc\n"
2009- "leak:pybind11::detail::make_static_property_type\n"
2010- "leak:pybind11::detail::make_object_base_type\n"
2011- "leak:pybind11::detail::get_internals\n"
2012- "leak:pybind11::detail::get_local_internals\n"
2013- "leak:libpython\n";
2014-}
@@ -10,6 +10,7 @@
10 10 
11#include <gtest/gtest.h>11#include <gtest/gtest.h>
12 12 
13+#include "common/python_runtime/ge_python_runtime_manager.h"
13#include "macro_utils/dt_public_scope.h"14#include "macro_utils/dt_public_scope.h"
14#include "generator/ge_generator.h"15#include "generator/ge_generator.h"
15#include "graph/utils/tensor_utils.h"16#include "graph/utils/tensor_utils.h"
@@ -44,6 +45,11 @@ const char *const kKernelLibName = "DNN_VM_GE_LOCAL";
44class UtestGeGenerator : public testing::Test {45class UtestGeGenerator : public testing::Test {
45 protected:46 protected:
46 void SetUp() {47 void SetUp() {
48+ const auto env_ptr = getenv("LD_PRELOAD");
49+ if (env_ptr != nullptr) {
50+ env = env_ptr;
51+ unsetenv("LD_PRELOAD");
52+ }
47 std::string opp_path = __FILE__;53 std::string opp_path = __FILE__;
48 opp_path = opp_path.substr(0, opp_path.rfind("/") + 1);54 opp_path = opp_path.substr(0, opp_path.rfind("/") + 1);
49 mmSetEnv(kEnvName, opp_path.c_str(), 1);55 mmSetEnv(kEnvName, opp_path.c_str(), 1);
@@ -81,6 +87,10 @@ class UtestGeGenerator : public testing::Test {
81 system(("rm -rf " + path_so).c_str());87 system(("rm -rf " + path_so).c_str());
82 OperatorFactoryImpl::operator_infershape_funcs_->erase("Data");88 OperatorFactoryImpl::operator_infershape_funcs_->erase("Data");
83 OperatorFactoryImpl::operator_infershape_funcs_->erase("NetOutput");89 OperatorFactoryImpl::operator_infershape_funcs_->erase("NetOutput");
90+ (void)GePythonRuntimeManager::Instance().ShutdownProcess();
91+ if (!env.empty()) {
92+ setenv("LD_PRELOAD", env.c_str(), 1);
93+ }
84 }94 }
85 95 
86 class FakeOpsKernelInfoStore : public OpsKernelInfoStore {96 class FakeOpsKernelInfoStore : public OpsKernelInfoStore {
@@ -106,6 +116,8 @@ class UtestGeGenerator : public testing::Test {
106 };116 };
107 };117 };
108 118 
119+ std::string env;
120+ 
109 class FakeOpsKernelBuilder : public OpsKernelBuilder {121 class FakeOpsKernelBuilder : public OpsKernelBuilder {
110 public:122 public:
111 FakeOpsKernelBuilder() = default;123 FakeOpsKernelBuilder() = default;
@@ -9,7 +9,9 @@
9 */9 */
10 10 
11#include <gtest/gtest.h>11#include <gtest/gtest.h>
12+#include <cstdlib>
12#include <fstream>13#include <fstream>
14+#include <string>
13#include "macro_utils/dt_public_scope.h"15#include "macro_utils/dt_public_scope.h"
14#include "graph/passes/memory_conflict/atomic_addr_clean_pass.h"16#include "graph/passes/memory_conflict/atomic_addr_clean_pass.h"
15#include "common/op/ge_op_utils.h"17#include "common/op/ge_op_utils.h"
@@ -29,12 +31,18 @@
29#include "engines/manager/opskernel_manager/ops_kernel_manager.h"31#include "engines/manager/opskernel_manager/ops_kernel_manager.h"
30#include "graph/debug/ge_attr_define.h"32#include "graph/debug/ge_attr_define.h"
31#include "common/plugin/plugin_manager.h"33#include "common/plugin/plugin_manager.h"
34+#include "ge_running_env/scoped_unset_ld_preload.h"
32 35 
33using namespace testing;36using namespace testing;
34using namespace domi;37using namespace domi;
35 38 
36namespace ge {39namespace ge {
37namespace {40namespace {
41+static Status GEInitializeWithoutLdPreload(const std::map<AscendString, AscendString> &options) {
42+ ScopedUnsetLdPreload guard;
43+ return GEInitialize(options);
44+}
45+ 
38class TestOpsKernelInfoStore : public OpsKernelInfoStore {46class TestOpsKernelInfoStore : public OpsKernelInfoStore {
39 public:47 public:
40 TestOpsKernelInfoStore() = default;48 TestOpsKernelInfoStore() = default;
@@ -101,7 +109,7 @@ class UtestGraphPassesAtomicAddrCleanPass : public Test {
101 ofs.close();109 ofs.close();
102 rename(json_tmp_path.c_str(), json_path.c_str());110 rename(json_tmp_path.c_str(), json_path.c_str());
103 std::map<AscendString, AscendString> options;111 std::map<AscendString, AscendString> options;
104- GEInitialize(options);112+ GEInitializeWithoutLdPreload(options);
105 {113 {
106 std::ifstream ifs(json_backup_path);114 std::ifstream ifs(json_backup_path);
107 if (ifs.is_open()) {115 if (ifs.is_open()) {
@@ -824,7 +832,7 @@ TEST_F(UtestGraphPassesAtomicAddrCleanPass, test_ge_init_fail) {
824 AtomicAddrCleanPass atomi_addr_clean_pass;832 AtomicAddrCleanPass atomi_addr_clean_pass;
825 EXPECT_EQ(atomi_addr_clean_pass.CallCompileOp(node_list), ge::GE_CLI_GE_NOT_INITIALIZED);833 EXPECT_EQ(atomi_addr_clean_pass.CallCompileOp(node_list), ge::GE_CLI_GE_NOT_INITIALIZED);
826 std::map<AscendString, AscendString> options;834 std::map<AscendString, AscendString> options;
827- GEInitialize(options);835+ GEInitializeWithoutLdPreload(options);
828}836}
829 837 
830} // namespace ge838} // namespace ge
@@ -22,11 +22,17 @@
22#include "engines/manager/opskernel_manager/ops_kernel_manager.h"22#include "engines/manager/opskernel_manager/ops_kernel_manager.h"
23#include "ge/ge_api.h"23#include "ge/ge_api.h"
24#include "api/gelib/gelib.h"24#include "api/gelib/gelib.h"
25+#include "ge_running_env/scoped_unset_ld_preload.h"
25 26 
26using namespace std;27using namespace std;
27using namespace ge;28using namespace ge;
28 29 
29namespace {30namespace {
31+static Status GEInitializeWithoutLdPreload(const std::map<AscendString, AscendString> &options) {
32+ ScopedUnsetLdPreload guard;
33+ return GEInitialize(options);
34+}
35+ 
30class TestOpsKernelInfoStore : public OpsKernelInfoStore {36class TestOpsKernelInfoStore : public OpsKernelInfoStore {
31 public:37 public:
32 TestOpsKernelInfoStore() = default;38 TestOpsKernelInfoStore() = default;
@@ -93,7 +99,7 @@ class UtestCompileNodesPass : public testing::Test {
93 protected:99 protected:
94 void SetUp() {100 void SetUp() {
95 std::map<AscendString, AscendString> options;101 std::map<AscendString, AscendString> options;
96- GEInitialize(options);102+ GEInitializeWithoutLdPreload(options);
97 ge::GELib::GetInstance()->OpsKernelManagerObj().ops_kernel_store_.clear();103 ge::GELib::GetInstance()->OpsKernelManagerObj().ops_kernel_store_.clear();
98 }104 }
99 void TearDown() {105 void TearDown() {
@@ -144,7 +150,7 @@ TEST_F(UtestCompileNodesPass, not_init_fail) {
144 EXPECT_EQ(pass_.Run(graph_), GE_CLI_GE_NOT_INITIALIZED);150 EXPECT_EQ(pass_.Run(graph_), GE_CLI_GE_NOT_INITIALIZED);
145 EXPECT_EQ(graph_->GetDirectNodesSize(), 3);151 EXPECT_EQ(graph_->GetDirectNodesSize(), 3);
146 std::map<AscendString, AscendString> options;152 std::map<AscendString, AscendString> options;
147- GEInitialize(options);153+ GEInitializeWithoutLdPreload(options);
148}154}
149 155 
150TEST_F(UtestCompileNodesPass, no_kernel_fail) {156TEST_F(UtestCompileNodesPass, no_kernel_fail) {
@@ -9,6 +9,7 @@
9 */9 */
10 10 
11#include <stdio.h>11#include <stdio.h>
12+#include <cstdlib>
12#include <fstream>13#include <fstream>
13#include <gtest/gtest.h>14#include <gtest/gtest.h>
14#include "api/aclgrph/option_utils.h"15#include "api/aclgrph/option_utils.h"
@@ -47,6 +48,7 @@
47#include "ge_running_env/fake_op.h"48#include "ge_running_env/fake_op.h"
48#include "ge_running_env/fake_graph_optimizer.h"49#include "ge_running_env/fake_graph_optimizer.h"
49#include "ge_running_env/fake_engine.h"50#include "ge_running_env/fake_engine.h"
51+#include "ge_running_env/scoped_unset_ld_preload.h"
50 52 
51const string AddNYes = "AddNYes";53const string AddNYes = "AddNYes";
52const char *const kEnvName = "ASCEND_OPP_PATH";54const char *const kEnvName = "ASCEND_OPP_PATH";
@@ -104,6 +106,12 @@ class UtestIrBuild : public testing::Test {
104 void TearDown() {}106 void TearDown() {}
105};107};
106 108 
109+template <typename Options>
110+static ge::graphStatus AclgrphBuildInitializeWithoutLdPreload(Options &options) {
111+ ScopedUnsetLdPreload guard;
112+ return ge::aclgrphBuildInitialize(options);
113+}
114+ 
107static std::vector<uint8_t> ReadFileToVector(const std::string &path) {115static std::vector<uint8_t> ReadFileToVector(const std::string &path) {
108 std::ifstream file(path, std::ios::binary);116 std::ifstream file(path, std::ios::binary);
109 if (!file.is_open()) {117 if (!file.is_open()) {
@@ -845,7 +853,7 @@ TEST(UtestIrBuild, check_aclgrphBundle) {
845 global_options[ge::OPTION_EXEC_HCCL_FLAG] = "0";853 global_options[ge::OPTION_EXEC_HCCL_FLAG] = "0";
846 global_options[ge::OPTION_HOST_ENV_OS] = "linux";854 global_options[ge::OPTION_HOST_ENV_OS] = "linux";
847 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";855 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
848- ge::aclgrphBuildInitialize(global_options);856+ AclgrphBuildInitializeWithoutLdPreload(global_options);
849 857 
850 Graph graph = BuildIrConstGraph1();858 Graph graph = BuildIrConstGraph1();
851 WeightRefreshableGraphs split_graphs;859 WeightRefreshableGraphs split_graphs;
@@ -1300,7 +1308,7 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test) {
1300 global_options[ge::OPTION_EXEC_HCCL_FLAG] = "0";1308 global_options[ge::OPTION_EXEC_HCCL_FLAG] = "0";
1301 global_options[ge::OPTION_HOST_ENV_OS] = "linux";1309 global_options[ge::OPTION_HOST_ENV_OS] = "linux";
1302 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";1310 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1303- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options);1311+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options);
1304 ge::aclgrphBuildFinalize();1312 ge::aclgrphBuildFinalize();
1305 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);1313 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
1306 1314 
@@ -1309,13 +1317,13 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test) {
1309 global_options1[ge::OPTION_HOST_ENV_OS] = "linux";1317 global_options1[ge::OPTION_HOST_ENV_OS] = "linux";
1310 global_options1[ge::OPTION_HOST_ENV_CPU] = "x86_64";1318 global_options1[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1311 global_options1[ge::OPTION_SCREEN_PRINT_MODE] = "enable";1319 global_options1[ge::OPTION_SCREEN_PRINT_MODE] = "enable";
1312- ret = ge::aclgrphBuildInitialize(global_options1);1320+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options1);
1313 ge::aclgrphBuildFinalize();1321 ge::aclgrphBuildFinalize();
1314 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);1322 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
1315 1323 
1316 std::map<AscendString, AscendString> global_options2;1324 std::map<AscendString, AscendString> global_options2;
1317 global_options1["ge.autoTuneMode"] = "RA";1325 global_options1["ge.autoTuneMode"] = "RA";
1318- ret = ge::aclgrphBuildInitialize(global_options1);1326+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options1);
1319 ge::aclgrphBuildFinalize();1327 ge::aclgrphBuildFinalize();
1320 EXPECT_NE(ret, ge::GRAPH_SUCCESS);1328 EXPECT_NE(ret, ge::GRAPH_SUCCESS);
1321 1329 
@@ -1324,7 +1332,7 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test) {
1324 global_options3["ge.deterministicLevel"] = "1";1332 global_options3["ge.deterministicLevel"] = "1";
1325 global_options3[ge::OPTION_HOST_ENV_OS] = "linux";1333 global_options3[ge::OPTION_HOST_ENV_OS] = "linux";
1326 global_options3[ge::OPTION_HOST_ENV_CPU] = "x86_64";1334 global_options3[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1327- ret = ge::aclgrphBuildInitialize(global_options3);1335+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options3);
1328 auto &options = GetMutableGlobalOptions();1336 auto &options = GetMutableGlobalOptions();
1329 auto it = options.find(ge::DETERMINISTIC);1337 auto it = options.find(ge::DETERMINISTIC);
1330 EXPECT_NE(it, options.end());1338 EXPECT_NE(it, options.end());
@@ -1343,7 +1351,7 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test) {
1343 global_options4[ge::OP_PRECISION_MODE] = "op_precision.ini";1351 global_options4[ge::OP_PRECISION_MODE] = "op_precision.ini";
1344 global_options4[ge::OPTION_HOST_ENV_OS] = "linux";1352 global_options4[ge::OPTION_HOST_ENV_OS] = "linux";
1345 global_options4[ge::OPTION_HOST_ENV_CPU] = "x86_64";1353 global_options4[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1346- ret = ge::aclgrphBuildInitialize(global_options4);1354+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options4);
1347 options = GetMutableGlobalOptions();1355 options = GetMutableGlobalOptions();
1348 it = options.find(ge::OP_PRECISION_MODE);1356 it = options.find(ge::OP_PRECISION_MODE);
1349 EXPECT_NE(it, options.end());1357 EXPECT_NE(it, options.end());
@@ -1355,13 +1363,13 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test) {
1355 1363 
1356 std::map<std::string, std::string> global_options5;1364 std::map<std::string, std::string> global_options5;
1357 global_options5[ge::ALLOW_HF32] = "1";1365 global_options5[ge::ALLOW_HF32] = "1";
1358- ret = ge::aclgrphBuildInitialize(global_options5);1366+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options5);
1359 ge::aclgrphBuildFinalize();1367 ge::aclgrphBuildFinalize();
1360 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);1368 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);
1361 1369 
1362 std::map<std::string, std::string> global_options6;1370 std::map<std::string, std::string> global_options6;
1363 global_options6[ge::OPTION_SCREEN_PRINT_MODE] = "0";1371 global_options6[ge::OPTION_SCREEN_PRINT_MODE] = "0";
1364- ret = ge::aclgrphBuildInitialize(global_options6);1372+ ret = AclgrphBuildInitializeWithoutLdPreload(global_options6);
1365 ge::aclgrphBuildFinalize();1373 ge::aclgrphBuildFinalize();
1366 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);1374 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);
1367}1375}
@@ -1371,7 +1379,7 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test_fail) {
1371 global_options2["ge.optionInvalid"] = "invalid";1379 global_options2["ge.optionInvalid"] = "invalid";
1372 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";1380 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";
1373 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";1381 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1374- EXPECT_EQ(ge::aclgrphBuildInitialize(global_options2), ge::GRAPH_SUCCESS);1382+ EXPECT_EQ(AclgrphBuildInitializeWithoutLdPreload(global_options2), ge::GRAPH_SUCCESS);
1375 ge::aclgrphBuildFinalize();1383 ge::aclgrphBuildFinalize();
1376}1384}
1377 1385 
@@ -1380,7 +1388,7 @@ TEST(UtestIrBuild, check_compression_optimize_conf_test) {
1380 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";1388 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";
1381 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";1389 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";
1382 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";1390 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1383- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options2);1391+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options2);
1384 ge::aclgrphBuildFinalize();1392 ge::aclgrphBuildFinalize();
1385 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);1393 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
1386}1394}
@@ -1390,7 +1398,7 @@ TEST(UtestIrBuild, check_virtual_type_test_success) {
1390 global_options2[ge::VIRTUAL_TYPE] = "1";1398 global_options2[ge::VIRTUAL_TYPE] = "1";
1391 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";1399 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";
1392 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";1400 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1393- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options2);1401+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options2);
1394 ge::aclgrphBuildFinalize();1402 ge::aclgrphBuildFinalize();
1395 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);1403 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
1396}1404}
@@ -1400,7 +1408,7 @@ TEST(UtestIrBuild, aclgrphBuildInitializeCheckJitCompileTrue) {
1400 global_options2[ge::VIRTUAL_TYPE] = "1";1408 global_options2[ge::VIRTUAL_TYPE] = "1";
1401 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";1409 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";
1402 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";1410 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1403- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options2);1411+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options2);
1404 ge::aclgrphBuildFinalize();1412 ge::aclgrphBuildFinalize();
1405 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);1413 EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
1406 1414 
@@ -1821,7 +1829,7 @@ TEST(UtestIrBuild, aclgrphBuildModelOm2UnsupportedGlobalOptionTest) {
1821 {ge::OPTION_HOST_ENV_OS, "linux"},1829 {ge::OPTION_HOST_ENV_OS, "linux"},
1822 {ge::OPTION_HOST_ENV_CPU, "x86_64"},1830 {ge::OPTION_HOST_ENV_CPU, "x86_64"},
1823 };1831 };
1824- ASSERT_EQ(ge::aclgrphBuildInitialize(global_options), ge::GRAPH_SUCCESS);1832+ ASSERT_EQ(AclgrphBuildInitializeWithoutLdPreload(global_options), ge::GRAPH_SUCCESS);
1825 GE_MAKE_GUARD(finalize_guard, [] { ge::aclgrphBuildFinalize(); });1833 GE_MAKE_GUARD(finalize_guard, [] { ge::aclgrphBuildFinalize(); });
1826 1834 
1827 Graph graph = BuildIrGraph1();1835 Graph graph = BuildIrGraph1();
@@ -1884,7 +1892,7 @@ TEST(UtestIrBuild, check_os_err) {
1884 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";1892 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";
1885 global_options2[ge::OPTION_HOST_ENV_OS] = "Linux";1893 global_options2[ge::OPTION_HOST_ENV_OS] = "Linux";
1886 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";1894 global_options2[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1887- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options2);1895+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options2);
1888 ge::aclgrphBuildFinalize();1896 ge::aclgrphBuildFinalize();
1889 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);1897 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);
1890}1898}
@@ -1894,7 +1902,7 @@ TEST(UtestIrBuild, check_cpu_err) {
1894 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";1902 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";
1895 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";1903 global_options2[ge::OPTION_HOST_ENV_OS] = "linux";
1896 global_options2[ge::OPTION_HOST_ENV_CPU] = "aaaaa";1904 global_options2[ge::OPTION_HOST_ENV_CPU] = "aaaaa";
1897- ge::graphStatus ret = ge::aclgrphBuildInitialize(global_options2);1905+ ge::graphStatus ret = AclgrphBuildInitializeWithoutLdPreload(global_options2);
1898 ge::aclgrphBuildFinalize();1906 ge::aclgrphBuildFinalize();
1899 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);1907 EXPECT_EQ(ret, ge::GRAPH_PARAM_INVALID);
1900}1908}
@@ -2047,7 +2055,7 @@ TEST(UtestIrBuild, ir_build_oo_init) {
2047 {ge::OPTION_HOST_ENV_CPU, "x86_64"},2055 {ge::OPTION_HOST_ENV_CPU, "x86_64"},
2048 {ge::OO_LEVEL, "O1"},2056 {ge::OO_LEVEL, "O1"},
2049 {OO_CONSTANT_FOLDING, "false"}};2057 {OO_CONSTANT_FOLDING, "false"}};
2050- EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2058+ EXPECT_EQ(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2051 2059 
2052 const std::map<std::string, std::string> build_options = {{ge::OO_LEVEL, "O1"}, {OO_CONSTANT_FOLDING, "true"}};2060 const std::map<std::string, std::string> build_options = {{ge::OO_LEVEL, "O1"}, {OO_CONSTANT_FOLDING, "true"}};
2053 EXPECT_NE(ge::aclgrphBuildModel(graph_1, build_options, model_1), GRAPH_SUCCESS);2061 EXPECT_NE(ge::aclgrphBuildModel(graph_1, build_options, model_1), GRAPH_SUCCESS);
@@ -2070,14 +2078,14 @@ TEST(UtestIrBuild, ir_build_oo_init_param_invalid) {
2070 2078 
2071 std::map<std::string, std::string> global_options;2079 std::map<std::string, std::string> global_options;
2072 global_options[OO_LEVEL] = "O4";2080 global_options[OO_LEVEL] = "O4";
2073- EXPECT_NE(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2081+ EXPECT_NE(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2074 2082 
2075 global_options[OO_LEVEL] = "O1";2083 global_options[OO_LEVEL] = "O1";
2076 global_options[OO_CONSTANT_FOLDING] = "False";2084 global_options[OO_CONSTANT_FOLDING] = "False";
2077- EXPECT_NE(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2085+ EXPECT_NE(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2078 2086 
2079 global_options[OO_CONSTANT_FOLDING] = "0";2087 global_options[OO_CONSTANT_FOLDING] = "0";
2080- EXPECT_NE(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2088+ EXPECT_NE(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2081 2089 
2082 std::map<std::string, std::string> build_options;2090 std::map<std::string, std::string> build_options;
2083 build_options[OO_LEVEL] = "O4";2091 build_options[OO_LEVEL] = "O4";
@@ -2112,7 +2120,7 @@ TEST(UtestIrBuild, ir_build_export_compile_stat_valid) {
2112 global_options[OPTION_EXPORT_COMPILE_STAT] = "0";2120 global_options[OPTION_EXPORT_COMPILE_STAT] = "0";
2113 global_options[ge::OPTION_HOST_ENV_OS] = "linux";2121 global_options[ge::OPTION_HOST_ENV_OS] = "linux";
2114 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";2122 global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
2115- EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2123+ EXPECT_EQ(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2116 EXPECT_NE(ge::aclgrphBuildModel(graph_1, build_options, model_1), GRAPH_SUCCESS);2124 EXPECT_NE(ge::aclgrphBuildModel(graph_1, build_options, model_1), GRAPH_SUCCESS);
2117 EXPECT_EQ(GetThreadLocalContext().GetOption(OPTION_EXPORT_COMPILE_STAT, opt_value), ge::GRAPH_SUCCESS);2125 EXPECT_EQ(GetThreadLocalContext().GetOption(OPTION_EXPORT_COMPILE_STAT, opt_value), ge::GRAPH_SUCCESS);
2118 EXPECT_EQ(opt_value, "0");2126 EXPECT_EQ(opt_value, "0");
@@ -2140,7 +2148,7 @@ TEST(UtestIrBuild, ir_build_export_compile_stat_invalid) {
2140 std::string opt_value("-1");2148 std::string opt_value("-1");
2141 std::map<std::string, std::string> global_options;2149 std::map<std::string, std::string> global_options;
2142 global_options[OPTION_EXPORT_COMPILE_STAT] = "3";2150 global_options[OPTION_EXPORT_COMPILE_STAT] = "3";
2143- EXPECT_NE(ge::aclgrphBuildInitialize(global_options), GRAPH_SUCCESS);2151+ EXPECT_NE(AclgrphBuildInitializeWithoutLdPreload(global_options), GRAPH_SUCCESS);
2144 2152 
2145 aclgrphBuildFinalize();2153 aclgrphBuildFinalize();
2146 system(("rm -rf " + opp_path).c_str());2154 system(("rm -rf " + opp_path).c_str());
@@ -259,6 +259,11 @@ REGISTER_LABEL_MAKER(CASE, FakeLabelMaker);
259class UtestGeApiV2 : public testing::Test {259class UtestGeApiV2 : public testing::Test {
260 protected:260 protected:
261 void SetUp() override {261 void SetUp() override {
262+ const auto env_ptr = getenv("LD_PRELOAD");
263+ if (env_ptr != nullptr) {
264+ env = env_ptr;
265+ unsetenv("LD_PRELOAD");
266+ }
262 OperatorFactoryImpl::RegisterInferShapeFunc("Data", [](Operator &op) { return GRAPH_SUCCESS; });267 OperatorFactoryImpl::RegisterInferShapeFunc("Data", [](Operator &op) { return GRAPH_SUCCESS; });
263 OperatorFactoryImpl::RegisterInferShapeFunc("Add", [](Operator &op) { return GRAPH_SUCCESS; });268 OperatorFactoryImpl::RegisterInferShapeFunc("Add", [](Operator &op) { return GRAPH_SUCCESS; });
264 OperatorFactoryImpl::RegisterInferShapeFunc("NetOutput", [](Operator &op) { return GRAPH_SUCCESS; });269 OperatorFactoryImpl::RegisterInferShapeFunc("NetOutput", [](Operator &op) { return GRAPH_SUCCESS; });
@@ -273,6 +278,9 @@ class UtestGeApiV2 : public testing::Test {
273 OperatorFactoryImpl::operator_infershape_funcs_->erase("Add");278 OperatorFactoryImpl::operator_infershape_funcs_->erase("Add");
274 OperatorFactoryImpl::operator_infershape_funcs_->erase("NetOutput");279 OperatorFactoryImpl::operator_infershape_funcs_->erase("NetOutput");
275 RuntimeStub::Reset();280 RuntimeStub::Reset();
281+ if (!env.empty()) {
282+ setenv("LD_PRELOAD", env.c_str(), 1);
283+ }
276 }284 }
277 285 
278 void CreateSharedLibrary(const std::string &path) {286 void CreateSharedLibrary(const std::string &path) {
@@ -288,6 +296,7 @@ class UtestGeApiV2 : public testing::Test {
288 system(cmd.c_str());296 system(cmd.c_str());
289 std::remove((path + ".cpp").c_str());297 std::remove((path + ".cpp").c_str());
290 }298 }
299+ std::string env;
291};300};
292 301 
293TEST_F(UtestGeApiV2, run_graph_with_stream) {302TEST_F(UtestGeApiV2, run_graph_with_stream) {
@@ -21,6 +21,25 @@
21using namespace std;21using namespace std;
22using namespace ge;22using namespace ge;
23 23 
24+extern "C" const char *__lsan_default_suppressions() {
25+ return "leak:_PyObject_Malloc\n"
26+ "leak:_PyObject_Realloc\n"
27+ "leak:PyType_GenericAlloc\n"
28+ "leak:PyType_Ready\n"
29+ "leak:PyObject_GC_New\n"
30+ "leak:PyObject_GC_NewVar\n"
31+ "leak:_PyObject_GC_Malloc\n"
32+ "leak:PyUnicode_New\n"
33+ "leak:Py_InitializeEx\n"
34+ "leak:PyImport_ImportModuleLevelObject\n"
35+ "leak:PyThread_allocate_lock\n"
36+ "leak:pybind11::detail::make_static_property_type\n"
37+ "leak:pybind11::detail::make_object_base_type\n"
38+ "leak:pybind11::detail::get_internals\n"
39+ "leak:pybind11::detail::get_local_internals\n"
40+ "leak:libpython\n";
41+}
42+ 
24int main(int argc, char **argv) {43int main(int argc, char **argv) {
25 // init the logging44 // init the logging
26 testing::InitGoogleTest(&argc, argv);45 testing::InitGoogleTest(&argc, argv);