From a9124547b7b20e6e0361539a812f6ddf4d59286e Mon Sep 17 00:00:00 2001 From: tushicheng <18829573815@163.com> Date: Fri, 25 Oct 2024 03:13:20 +0000 Subject: [PATCH] fix core with unexpected stack_addr and stack_size --- deps/oblib/src/common/ob_smart_call.h | 87 ++++++++++++++++++--------- src/observer/main.cpp | 24 +++++++- 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/deps/oblib/src/common/ob_smart_call.h b/deps/oblib/src/common/ob_smart_call.h index 0cf58ab02..3954919f6 100644 --- a/deps/oblib/src/common/ob_smart_call.h +++ b/deps/oblib/src/common/ob_smart_call.h @@ -28,15 +28,33 @@ RLOCAL_EXTERN(int64_t, all_stack_size); int jump_call(void * arg_, int(*func_) (void*), void* stack_addr); -inline int call_with_new_stack(void * arg_, int(*func_) (void*)) +inline int call_with_new_stack(void * arg_, int(*func_) (void*), void *stack_addr, size_t stack_size) { int ret = OB_SUCCESS; #if defined(__x86_64__) || defined(__aarch64__) void *ori_stack_addr = nullptr; size_t ori_stack_size = 0; - void *stack_addr = nullptr; + if (OB_FAIL(get_stackattr(ori_stack_addr, ori_stack_size))) { + } else { + // To prevent the check_stack_overflow call before the jump + // Do not introduce other code between the two set_stackattr + set_stackattr(stack_addr, stack_size); + ret = jump_call(arg_, func_, (char *)stack_addr + stack_size); + set_stackattr(ori_stack_addr, ori_stack_size); + } +#else + ret = func_(arg_); +#endif + return ret; +} + +inline int alloc_stack(const size_t stack_size, void *&stack_addr) +{ + int ret = OB_SUCCESS; + void *ori_stack_addr = nullptr; + size_t ori_stack_size = 0; + stack_addr = nullptr; uint64_t tenant_id = GET_TENANT_ID() == 0 ? 500 : GET_TENANT_ID(); - const int64_t stack_size = STACK_PER_EXTEND; if (OB_FAIL(get_stackattr(ori_stack_addr, ori_stack_size))) { } else if (FALSE_IT(all_stack_size = 0 == all_stack_size ? ori_stack_size : all_stack_size)) { @@ -46,22 +64,38 @@ inline int call_with_new_stack(void * arg_, int(*func_) (void*)) ret = OB_ALLOCATE_MEMORY_FAILED; } else { all_stack_size += stack_size; - // To prevent the check_stack_overflow call before the jump - // Do not introduce other code between the two set_stackattr - set_stackattr(stack_addr, stack_size); - ret = jump_call(arg_, func_, (char *)stack_addr + stack_size); - set_stackattr(ori_stack_addr, ori_stack_size); - lib::g_stack_allocer.dealloc(stack_addr); - all_stack_size -= stack_size; } -#else - ret = func_(arg_); -#endif return ret; } +inline void dealloc_stack(void *stack_addr, size_t stack_size) +{ + lib::g_stack_allocer.dealloc(stack_addr); + all_stack_size -= stack_size; +} + #ifndef OB_USE_ASAN +#define CALL_WITH_NEW_STACK(func, stack_addr, stack_size) \ + ({ \ + int ret = OB_SUCCESS; \ + std::function f = [&]() { \ + int ret = OB_SUCCESS; \ + try { \ + in_try_stmt = true; \ + ret = func; \ + in_try_stmt = false; \ + } catch (OB_BASE_EXCEPTION &except) { \ + ret = except.get_errno(); \ + in_try_stmt = false; \ + } \ + return ret; \ + }; \ + int(*func_) (void*) = [](void *arg) { return (*(decltype(f)*)(arg))(); };\ + void * arg_ = &f; \ + ret = call_with_new_stack(arg_, func_, stack_addr, stack_size); \ + ret; \ + }) #define SMART_CALL(func) \ ({ \ int ret = OB_SUCCESS; \ @@ -70,25 +104,22 @@ inline int call_with_new_stack(void * arg_, int(*func_) (void*)) } else if (!is_overflow) { \ ret = func; \ } else { \ - std::function f = [&]() { \ - int ret = OB_SUCCESS; \ - try { \ - in_try_stmt = true; \ - ret = func; \ - in_try_stmt = false; \ - } catch (OB_BASE_EXCEPTION &except) { \ - ret = except.get_errno(); \ - in_try_stmt = false; \ - } \ - return ret; \ - }; \ - int(*func_) (void*) = [](void *arg) { return (*(decltype(f)*)(arg))(); };\ - void * arg_ = &f; \ - ret = call_with_new_stack(arg_, func_); \ + const size_t stack_size = STACK_PER_EXTEND; \ + void *stack_addr = nullptr; \ + if (OB_SUCC(alloc_stack(stack_size, stack_addr))) { \ + ret = CALL_WITH_NEW_STACK(func, stack_addr, stack_size); \ + dealloc_stack(stack_addr, stack_size); \ + } \ } \ ret; \ }) #else +#define CALL_WITH_NEW_STACK(func, stack_addr, stack_size) \ + ({ \ + int ret = OB_SUCCESS; \ + ret = func; \ + ret; \ + }) #define SMART_CALL(func) \ ({ \ int ret = OB_SUCCESS; \ diff --git a/src/observer/main.cpp b/src/observer/main.cpp index f1a6c730a..11f2e16e8 100644 --- a/src/observer/main.cpp +++ b/src/observer/main.cpp @@ -439,7 +439,7 @@ void print_all_thread(const char* desc, uint64_t tenant_id) MPRINT("============= [%s] finish to show unstopped thread =============", desc); } -int main(int argc, char *argv[]) +int inner_main(int argc, char *argv[]) { // temporarily unlimited memory before init config set_memory_limit(INT_MAX64); @@ -617,3 +617,25 @@ int main(int argc, char *argv[]) print_all_thread("AFTER_DESTROY", OB_SERVER_TENANT_ID); return ret; } + +int main(int argc, char *argv[]) +{ + int ret = OB_SUCCESS; + size_t stack_size = 16<<20; + struct rlimit limit; + if (0 == getrlimit(RLIMIT_STACK, &limit)) { + if (RLIM_INFINITY != limit.rlim_cur) { + stack_size = limit.rlim_cur; + } + } + void *stack_addr = ::mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == stack_addr) { + ret = OB_ERR_UNEXPECTED; + } else { + ret = CALL_WITH_NEW_STACK(inner_main(argc, argv), stack_addr, stack_size); + if (-1 == ::munmap(stack_addr, stack_size)) { + ret = OB_ERR_UNEXPECTED; + } + } + return ret; +} \ No newline at end of file