fix core with unexpected stack_addr and stack_size

This commit is contained in:
tushicheng 2024-10-25 03:13:20 +00:00 committed by ob-robot
parent 866cb1d50e
commit a9124547b7
2 changed files with 82 additions and 29 deletions

View File

@ -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<int()> 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<int()> 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; \

View File

@ -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;
}