From a1f368d6b9b60e1ad7ef54b86f1100299805e600 Mon Sep 17 00:00:00 2001 From: obdev Date: Mon, 7 Nov 2022 05:05:35 +0000 Subject: [PATCH] fix udf dynamic memory leak of 4.0 branch --- src/pl/ob_pl.cpp | 15 +++++++++++++-- src/pl/ob_pl.h | 3 +++ src/pl/ob_pl_package.cpp | 1 + src/sql/engine/cmd/ob_routine_executor.cpp | 1 + src/sql/engine/dml/ob_trigger_handler.cpp | 2 +- src/sql/engine/expr/ob_expr_udf.cpp | 18 ++++++++++++++++-- .../ob_pl_user_defined_agg_function.cpp | 1 + 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index 27231d5e0a..29570ec9c1 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -187,7 +187,7 @@ int ObPL::init(common::ObMySQLProxy &sql_proxy) return ret; } -ObPLCtx::~ObPLCtx() +void ObPLCtx::reset_obj() { int tmp_ret = OB_SUCCESS; for (int64_t i = 0; i < objects_.count(); ++i) { @@ -198,6 +198,11 @@ ObPLCtx::~ObPLCtx() objects_.reset(); } +ObPLCtx::~ObPLCtx() +{ + reset_obj(); +} + void ObPL::destory() { codegen_lock_.destroy(); @@ -281,6 +286,7 @@ int ObPL::execute_proc(ObPLExecCtx &ctx, ctx.exec_ctx_->get_sql_ctx()->schema_guard_ = &schema_guard; try { if (OB_FAIL(pl.execute(*ctx.exec_ctx_, + ctx.exec_ctx_->get_allocator(), package_id, proc_id, path_array, @@ -1148,6 +1154,7 @@ int ObPLContext::set_subprogram_var_from_local( // for common execute routine. int ObPL::execute(ObExecContext &ctx, + ObIAllocator &allocator, ObPLPackageGuard &package_guard, ObPLFunction &routine, ParamStore *params, @@ -1166,7 +1173,7 @@ int ObPL::execute(ObExecContext &ctx, ObObj local_result(ObMaxType); int local_status = OB_SUCCESS; - ObPLExecState pl(ctx.get_allocator(), + ObPLExecState pl(allocator, ctx, package_guard, routine, @@ -1279,6 +1286,7 @@ int ObPL::execute(ObExecContext &ctx, const ObStmtNodeTree *block) try { // execute it. OZ (execute(ctx, + ctx.get_allocator(), *(ctx.get_package_guard()), *routine, NULL, // params @@ -1362,6 +1370,7 @@ int ObPL::execute(ObExecContext &ctx, try { // execute it... OZ (execute(ctx, + ctx.get_allocator(), *(ctx.get_package_guard()), *routine, ¶ms, @@ -1391,6 +1400,7 @@ int ObPL::execute(ObExecContext &ctx, // for normal routine int ObPL::execute(ObExecContext &ctx, + ObIAllocator &allocator, uint64_t package_id, uint64_t routine_id, const ObIArray &subprogram_path, @@ -1509,6 +1519,7 @@ int ObPL::execute(ObExecContext &ctx, try { // execute it ... OZ (execute(ctx, + allocator, *(ctx.get_package_guard()), *routine, ¶ms, diff --git a/src/pl/ob_pl.h b/src/pl/ob_pl.h index 068516048b..d5fabf9cd2 100644 --- a/src/pl/ob_pl.h +++ b/src/pl/ob_pl.h @@ -612,6 +612,7 @@ public: int add(ObObj &obj) { return objects_.push_back(obj); } + void reset_obj(); common::ObIArray& get_objects() { return objects_; } private: // 用于收集在PL执行过程中使用到的Allocator, @@ -1012,6 +1013,7 @@ public: // for normal routine or package routine int execute(sql::ObExecContext &ctx, + ObIAllocator &allocator, uint64_t package_id, uint64_t routine_id, const ObIArray &subprogram_path, @@ -1056,6 +1058,7 @@ private: // for inner common execute int execute(sql::ObExecContext &ctx, + ObIAllocator &allocator, ObPLPackageGuard &package_guard, ObPLFunction &routine, ParamStore *params, diff --git a/src/pl/ob_pl_package.cpp b/src/pl/ob_pl_package.cpp index 70f4abf76c..7aca005a4e 100644 --- a/src/pl/ob_pl_package.cpp +++ b/src/pl/ob_pl_package.cpp @@ -255,6 +255,7 @@ int ObPLPackage::execute_init_routine(ObIAllocator &allocator, ObExecContext &ex int status; ObSEArray subp_path; OZ (pl_engine->execute(exec_ctx, + exec_ctx.get_allocator(), init_routine->get_package_id(), init_routine->get_routine_id(), subp_path, diff --git a/src/sql/engine/cmd/ob_routine_executor.cpp b/src/sql/engine/cmd/ob_routine_executor.cpp index 78af1f48ad..2c952c1885 100644 --- a/src/sql/engine/cmd/ob_routine_executor.cpp +++ b/src/sql/engine/cmd/ob_routine_executor.cpp @@ -145,6 +145,7 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st int64_t pkg_id = stmt.is_udt_routine() ? share::schema::ObUDTObjectType::mask_object_id(package_id) : package_id; if (OB_FAIL(ctx.get_pl_engine()->execute(ctx, + ctx.get_allocator(), pkg_id, routine_id, path, diff --git a/src/sql/engine/dml/ob_trigger_handler.cpp b/src/sql/engine/dml/ob_trigger_handler.cpp index c6b268b7d2..03b6398b14 100644 --- a/src/sql/engine/dml/ob_trigger_handler.cpp +++ b/src/sql/engine/dml/ob_trigger_handler.cpp @@ -403,7 +403,7 @@ int TriggerHandle::calc_trigger_routine( trigger_id = ObTriggerInfo::get_trigger_spec_package_id(trigger_id); OV (OB_NOT_NULL(exec_ctx.get_pl_engine())); OZ (exec_ctx.get_pl_engine()->execute( - exec_ctx, trigger_id, routine_id, path, params, nocopy_params, result), + exec_ctx, exec_ctx.get_allocator(), trigger_id, routine_id, path, params, nocopy_params, result), trigger_id, routine_id, params); return ret; } diff --git a/src/sql/engine/expr/ob_expr_udf.cpp b/src/sql/engine/expr/ob_expr_udf.cpp index 93e013e0b7..d05bd08166 100644 --- a/src/sql/engine/expr/ob_expr_udf.cpp +++ b/src/sql/engine/expr/ob_expr_udf.cpp @@ -407,6 +407,7 @@ int ObExprUDF::build_udf_ctx(int64_t udf_ctx_id, int ObExprUDF::eval_udf(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) { int ret = OB_SUCCESS; + ObObj tmp_result; ObObj result; pl::ObPL *pl_engine = nullptr; ParamStore *udf_params = nullptr; @@ -479,17 +480,20 @@ int ObExprUDF::eval_udf(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) CK (0 < udf_params->count()); OZ (ns.init_complex_obj(alloc, pl_type, udf_params->at(0), false, false)); } + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); try { int64_t package_id = info->is_udt_udf_ ? share::schema::ObUDTObjectType::mask_object_id(info->udf_package_id_) : info->udf_package_id_; OZ(pl_engine->execute(ctx.exec_ctx_, + info->is_called_in_sql_ ? tmp_alloc_g.get_allocator() + : alloc, package_id, info->udf_id_, info->subprogram_path_, *udf_params, info->nocopy_params_, - result, + tmp_result, nullptr, false, true, @@ -499,12 +503,22 @@ int ObExprUDF::eval_udf(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) info->udf_id_, info->udf_package_id_, info->is_udt_udf_, - result, + tmp_result, package_id); } catch(...) { // OZ(after_calc_result(schema_guard, sql_ctx, ctx.exec_ctx_)); throw; } + if (OB_SUCC(ret)) { + if (tmp_result.is_pl_extend()) { + OZ (pl::ObUserDefinedType::deep_copy_obj(alloc, tmp_result, result, true)); + } else { + OZ (deep_copy_obj(alloc, tmp_result, result)); + } + if (info->is_called_in_sql_) { + OX (ctx.exec_ctx_.get_pl_ctx()->reset_obj()); + } + } if (OB_SUCC(ret) && info->is_udt_cons_) { pl::ObPLComposite *obj_self = reinterpret_cast(udf_params->at(0).get_ext()); CK (OB_NOT_NULL(obj_self)); diff --git a/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp b/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp index ebade084e4..d0dcb8cb54 100644 --- a/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp +++ b/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp @@ -110,6 +110,7 @@ int ObPlAggUdfFunction::call_pl_engine_exectue_udf(ParamStore& udf_params, LOG_WARN("udf parameter number is not equal to params desc count", K(ret), K(udf_params.count()), K(routine_info->get_param_count())); } else if (OB_FAIL(pl_engine->execute(*exec_ctx_, + exec_ctx_->get_allocator(), -1, routine_info->get_routine_id(), empty_subprogram_path,