fix core with unexpected stack_addr and stack_size
This commit is contained in:
parent
866cb1d50e
commit
a9124547b7
87
deps/oblib/src/common/ob_smart_call.h
vendored
87
deps/oblib/src/common/ob_smart_call.h
vendored
@ -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; \
|
||||
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user