[CP] fix T_OP_STACK_OVERFLOW_CHECK reset child ptr leads core
This commit is contained in:
		| @ -1260,28 +1260,6 @@ int ObStaticEngineExprCG::alloc_so_check_exprs(const ObIArray<ObRawExpr *> &raw_ | |||||||
|     if (OB_SUCC(ret) && stack_check_expr_cnt > 0) { |     if (OB_SUCC(ret) && stack_check_expr_cnt > 0) { | ||||||
|       LOG_TRACE("stack check expr needed", |       LOG_TRACE("stack check expr needed", | ||||||
|                 K(exprs.count()), K(stack_check_expr_cnt), K(max_call_depth)); |                 K(exprs.count()), K(stack_check_expr_cnt), K(max_call_depth)); | ||||||
|       ObExpr *ori_base = exprs.get_data(); |  | ||||||
|       OZ(exprs.reserve(exprs.count() + stack_check_expr_cnt)); |  | ||||||
|       ObExpr *base = exprs.get_data(); |  | ||||||
|       // relocate expr ptr |  | ||||||
|       if (OB_SUCC(ret) && ori_base != base) { |  | ||||||
|         const int64_t offset = reinterpret_cast<char *>(base) - reinterpret_cast<char *>(ori_base); |  | ||||||
|         FOREACH_CNT(e, raw_exprs) { |  | ||||||
|           (*e)->set_rt_expr(reinterpret_cast<ObExpr *>( |  | ||||||
|                   reinterpret_cast<char *>(get_rt_expr(**e)) + offset)); |  | ||||||
|         } |  | ||||||
|         FOREACH_CNT(e, exprs_call_depth) { |  | ||||||
|           *reinterpret_cast<char **>(&e->expr_) += offset; |  | ||||||
|         } |  | ||||||
|         FOREACH_CNT(e, exprs) { |  | ||||||
|           for (int64_t i = 0; i < e->parent_cnt_; i++) { |  | ||||||
|             *reinterpret_cast<char **>(&e->parents_[i]) += offset; |  | ||||||
|           } |  | ||||||
|           for (int64_t i = 0; i < e->arg_cnt_; i++) { |  | ||||||
|             *reinterpret_cast<char **>(&e->args_[i]) += offset; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       FOREACH_CNT_X(ecd, exprs_call_depth, OB_SUCC(ret)) { |       FOREACH_CNT_X(ecd, exprs_call_depth, OB_SUCC(ret)) { | ||||||
|         if (ecd->need_stack_check_) { |         if (ecd->need_stack_check_) { | ||||||
| @ -1295,7 +1273,7 @@ int ObStaticEngineExprCG::alloc_so_check_exprs(const ObIArray<ObRawExpr *> &raw_ | |||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           if (OB_SUCC(ret) && e->parent_cnt_ > 0) { |           if (OB_SUCC(ret) && e->parent_cnt_ > 0) { | ||||||
|             OZ(add_so_check_expr_above(exprs, e)); |             e->need_stack_check_ = true; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } // END FOREACH_CNT_X |       } // END FOREACH_CNT_X | ||||||
| @ -1304,52 +1282,6 @@ int ObStaticEngineExprCG::alloc_so_check_exprs(const ObIArray<ObRawExpr *> &raw_ | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ObStaticEngineExprCG::add_so_check_expr_above(ObIArray<ObExpr> &exprs, ObExpr *e) |  | ||||||
| { |  | ||||||
|   int ret = OB_SUCCESS; |  | ||||||
|   ObExpr *base = exprs.get_data(); |  | ||||||
|   CK(NULL != e); |  | ||||||
|   CK(e->parent_cnt_ > 0 && e->arg_cnt_ > 0); |  | ||||||
|   OZ(exprs.push_back(*e)); |  | ||||||
|   CK(base == exprs.get_data()); |  | ||||||
|   if (OB_SUCC(ret)) { |  | ||||||
|     // stack overflow check expr point to the same ObDatum of child. |  | ||||||
|     ObExpr *so = &exprs.at(exprs.count() - 1); |  | ||||||
|     so->type_ = T_OP_STACK_OVERFLOW_CHECK; |  | ||||||
|     so->extra_ = 0; |  | ||||||
|     so->inner_functions_ = 0; |  | ||||||
|     so->inner_func_cnt_ = 0; |  | ||||||
|     ObExpr **parents = static_cast<ObExpr **>(allocator_.alloc(sizeof(ObExpr *) * 2)); |  | ||||||
|     if (NULL == parents) { |  | ||||||
|       ret = OB_ALLOCATE_MEMORY_FAILED; |  | ||||||
|       LOG_WARN("allocate memory failed", K(ret)); |  | ||||||
|     } else { |  | ||||||
|       ObExpr **args = parents + 1; |  | ||||||
|  |  | ||||||
|       parents[0] = so; |  | ||||||
|       args[0] = e; |  | ||||||
|  |  | ||||||
|       e->parents_ = parents; |  | ||||||
|       e->parent_cnt_ = 1; |  | ||||||
|       so->args_ = args; |  | ||||||
|       so->arg_cnt_ = 1; |  | ||||||
|  |  | ||||||
|       for (int64_t i = 0; i < so->parent_cnt_; i++) { |  | ||||||
|         ObExpr *p = so->parents_[i]; |  | ||||||
|         for (int64_t j = 0; j < p->arg_cnt_; j++) { |  | ||||||
|           if (p->args_[j] == e) { |  | ||||||
|             p->args_[j] = so; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       so->eval_func_ = ObExprUtil::eval_stack_overflow_check; |  | ||||||
|       so->eval_batch_func_ = ObExprUtil::eval_batch_stack_overflow_check; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int ObStaticEngineExprCG::calc_exprs_res_buf_len(const ObIArray<ObRawExpr *> &raw_exprs) | int ObStaticEngineExprCG::calc_exprs_res_buf_len(const ObIArray<ObRawExpr *> &raw_exprs) | ||||||
| { | { | ||||||
|   int ret = OB_SUCCESS; |   int ret = OB_SUCCESS; | ||||||
|  | |||||||
| @ -196,9 +196,6 @@ private: | |||||||
|   // alloc stack overflow check exprs. |   // alloc stack overflow check exprs. | ||||||
|   int alloc_so_check_exprs(const common::ObIArray<ObRawExpr *> &raw_exprs, |   int alloc_so_check_exprs(const common::ObIArray<ObRawExpr *> &raw_exprs, | ||||||
|                            ObExprFrameInfo &expr_info); |                            ObExprFrameInfo &expr_info); | ||||||
|   // add stack overflow check expr above %e |  | ||||||
|   int add_so_check_expr_above(common::ObIArray<ObExpr> &exprs, |  | ||||||
|                               ObExpr *e); |  | ||||||
|  |  | ||||||
|   // calculate res_buf_len_ for exprs' datums |   // calculate res_buf_len_ for exprs' datums | ||||||
|   int calc_exprs_res_buf_len(const common::ObIArray<ObRawExpr *> &raw_exprs); |   int calc_exprs_res_buf_len(const common::ObIArray<ObRawExpr *> &raw_exprs); | ||||||
|  | |||||||
| @ -609,16 +609,20 @@ int ObExpr::eval_one_datum_of_batch(ObEvalCtx &ctx, common::ObDatum *&datum) con | |||||||
|   } |   } | ||||||
|   datum = reinterpret_cast<ObDatum *>(frame + datum_off_) + ctx.get_batch_idx(); |   datum = reinterpret_cast<ObDatum *>(frame + datum_off_) + ctx.get_batch_idx(); | ||||||
|   if (need_evaluate) { |   if (need_evaluate) { | ||||||
|     reset_datum_ptr(frame, ctx.get_batch_size(), ctx.get_batch_idx()); |     if (OB_UNLIKELY(need_stack_check_) && OB_FAIL(check_stack_overflow())) { | ||||||
|     ret = eval_func_(*this, ctx, *datum); |       SQL_LOG(WARN, "failed to check stack overflow", K(ret)); | ||||||
|     if (OB_SUCC(ret)) { |  | ||||||
|       ObBitVector *evaluated_flags = to_bit_vector(frame + eval_flags_off_); |  | ||||||
|       evaluated_flags->set(ctx.get_batch_idx()); |  | ||||||
|     } else { |     } else { | ||||||
|       datum->set_null(); |       reset_datum_ptr(frame, ctx.get_batch_size(), ctx.get_batch_idx()); | ||||||
|     } |       ret = eval_func_(*this, ctx, *datum); | ||||||
|     if (datum->is_null()) { |       if (OB_SUCC(ret)) { | ||||||
|       info->notnull_ = false; |         ObBitVector *evaluated_flags = to_bit_vector(frame + eval_flags_off_); | ||||||
|  |         evaluated_flags->set(ctx.get_batch_idx()); | ||||||
|  |       } else { | ||||||
|  |         datum->set_null(); | ||||||
|  |       } | ||||||
|  |       if (datum->is_null()) { | ||||||
|  |         info->notnull_ = false; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @ -655,17 +659,21 @@ int ObExpr::do_eval_batch(ObEvalCtx &ctx, | |||||||
|       info->notnull_ = false; |       info->notnull_ = false; | ||||||
|       info->point_to_frame_ = true; |       info->point_to_frame_ = true; | ||||||
|     } |     } | ||||||
|     ret = (*eval_batch_func_)(*this, ctx, skip, size); |     if (OB_UNLIKELY(need_stack_check_) && OB_FAIL(check_stack_overflow())) { | ||||||
|     if (OB_SUCC(ret)) { |       SQL_LOG(WARN, "failed to check stack overflow", K(ret)); | ||||||
|       if (!info->evaluated_) { |  | ||||||
|         info->cnt_ = size; |  | ||||||
|         info->evaluated_ = true; |  | ||||||
|       } |  | ||||||
|     } else { |     } else { | ||||||
|       ObDatum *datum = reinterpret_cast<ObDatum *>(frame + datum_off_); |       ret = (*eval_batch_func_)(*this, ctx, skip, size); | ||||||
|       ObDatum *datum_end = datum + size; |       if (OB_SUCC(ret)) { | ||||||
|       for (; datum < datum_end; datum += 1) { |         if (!info->evaluated_) { | ||||||
|         datum->set_null(); |           info->cnt_ = size; | ||||||
|  |           info->evaluated_ = true; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         ObDatum *datum = reinterpret_cast<ObDatum *>(frame + datum_off_); | ||||||
|  |         ObDatum *datum_end = datum + size; | ||||||
|  |         for (; datum < datum_end; datum += 1) { | ||||||
|  |           datum->set_null(); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ | |||||||
| #include "sql/engine/ob_serializable_function.h" | #include "sql/engine/ob_serializable_function.h" | ||||||
| #include "objit/common/ob_item_type.h" | #include "objit/common/ob_item_type.h" | ||||||
| #include "sql/engine/ob_bit_vector.h" | #include "sql/engine/ob_bit_vector.h" | ||||||
|  | #include "common/ob_common_utility.h" | ||||||
|  |  | ||||||
| namespace oceanbase | namespace oceanbase | ||||||
| { | { | ||||||
| @ -610,6 +611,7 @@ public: | |||||||
|       uint64_t is_static_const_:1; // is const during the whole execution |       uint64_t is_static_const_:1; // is const during the whole execution | ||||||
|       uint64_t is_boolean_:1; // to distinguish result of this expr between and int tc |       uint64_t is_boolean_:1; // to distinguish result of this expr between and int tc | ||||||
|       uint64_t is_dynamic_const_:1; // is const during the subplan execution, including exec param |       uint64_t is_dynamic_const_:1; // is const during the subplan execution, including exec param | ||||||
|  |       uint64_t need_stack_check_:1; // the expression tree depth needs to check whether the stack overflows | ||||||
|     }; |     }; | ||||||
|     uint64_t flag_; |     uint64_t flag_; | ||||||
|   }; |   }; | ||||||
| @ -976,7 +978,6 @@ OB_INLINE int ObExpr::eval(ObEvalCtx &ctx, common::ObDatum *&datum) const | |||||||
|   OB_ASSERT(NULL != frame); |   OB_ASSERT(NULL != frame); | ||||||
| 	datum = (ObDatum *)(frame + datum_off_); | 	datum = (ObDatum *)(frame + datum_off_); | ||||||
|   ObEvalInfo *eval_info = (ObEvalInfo *)(frame + eval_info_off_); |   ObEvalInfo *eval_info = (ObEvalInfo *)(frame + eval_info_off_); | ||||||
|  |  | ||||||
|   if (is_batch_result()) { |   if (is_batch_result()) { | ||||||
|     if (NULL == eval_func_ || eval_info->projected_) { |     if (NULL == eval_func_ || eval_info->projected_) { | ||||||
|       datum = datum + ctx.get_batch_idx(); |       datum = datum + ctx.get_batch_idx(); | ||||||
| @ -985,14 +986,18 @@ OB_INLINE int ObExpr::eval(ObEvalCtx &ctx, common::ObDatum *&datum) const | |||||||
|     } |     } | ||||||
|   } else if (NULL != eval_func_ && !eval_info->evaluated_) { |   } else if (NULL != eval_func_ && !eval_info->evaluated_) { | ||||||
| 	// do nothing for const/column reference expr or already evaluated expr | 	// do nothing for const/column reference expr or already evaluated expr | ||||||
| 		if (datum->ptr_ != frame + res_buf_off_) { |     if (OB_UNLIKELY(need_stack_check_) && OB_FAIL(check_stack_overflow())) { | ||||||
| 			datum->ptr_ = frame + res_buf_off_; |       SQL_LOG(WARN, "failed to check stack overflow", K(ret)); | ||||||
| 		} |  | ||||||
| 		ret = eval_func_(*this, ctx, *datum); |  | ||||||
|     if (OB_LIKELY(common::OB_SUCCESS == ret)) { |  | ||||||
|       eval_info->evaluated_ = true; |  | ||||||
|     } else { |     } else { | ||||||
|       datum->set_null(); |       if (datum->ptr_ != frame + res_buf_off_) { | ||||||
|  |         datum->ptr_ = frame + res_buf_off_; | ||||||
|  |       } | ||||||
|  |       ret = eval_func_(*this, ctx, *datum); | ||||||
|  |       if (OB_LIKELY(common::OB_SUCCESS == ret)) { | ||||||
|  |         eval_info->evaluated_ = true; | ||||||
|  |       } else { | ||||||
|  |         datum->set_null(); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 	} | 	} | ||||||
| 	return ret; | 	return ret; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 obdev
					obdev