diff --git a/cmake/Env.cmake b/cmake/Env.cmake index a512effe4..866e87eee 100644 --- a/cmake/Env.cmake +++ b/cmake/Env.cmake @@ -23,7 +23,6 @@ ob_define(OB_CMAKE_RULES_CHECK ON) ob_define(OB_STATIC_LINK_LGPL_DEPS ON) ob_define(HOTFUNC_PATH "${CMAKE_SOURCE_DIR}/hotfuncs.txt") ob_define(OB_BUILD_CCLS OFF) -ob_define(ENABLE_EXE_PIE OFF) # 'ENABLE_PERF_MODE' use for offline system insight performance test # PERF_MODE macro controls many special code path in system @@ -65,11 +64,6 @@ if(NOT OB_BUILD_CDC) add_definitions(-DENABLE_INITIAL_EXEC_TLS_MODEL) endif() -ob_define(OB_EXE_LINKER_OPT "") -if (ENABLE_EXE_PIE) - set(OB_EXE_LINKER_OPT "-pie") -endif() - set(OB_OBJCOPY_BIN "${DEVTOOLS_DIR}/bin/objcopy") # NO RELERO: -Wl,-znorelro @@ -104,7 +98,7 @@ if (OB_USE_CLANG) set(CMAKE_C_FLAGS "--gcc-toolchain=${GCC9} ${DEBUG_PREFIX} ${AUTO_FDO_OPT} ${THIN_LTO_OPT} -fcolor-diagnostics ${REORDER_COMP_OPT} -fmax-type-align=8 ${CMAKE_ASAN_FLAG}") set(CMAKE_CXX_LINK_FLAGS "${LD_OPT} ${THIN_LTO_CONCURRENCY_LINK} --gcc-toolchain=${GCC9} ${DEBUG_PREFIX} ${AUTO_FDO_OPT}") set(CMAKE_SHARED_LINKER_FLAGS "${LD_OPT} -Wl,-z,noexecstack ${THIN_LTO_CONCURRENCY_LINK} ${REORDER_LINK_OPT}") - set(CMAKE_EXE_LINKER_FLAGS "${LD_OPT} -Wl,-z,noexecstack ${THIN_LTO_CONCURRENCY_LINK} ${REORDER_LINK_OPT} ${OB_EXE_LINKER_OPT} ${CMAKE_COVERAGE_EXE_LINKER_OPTIONS}") + set(CMAKE_EXE_LINKER_FLAGS "${LD_OPT} -Wl,-z,noexecstack -pie ${THIN_LTO_CONCURRENCY_LINK} ${REORDER_LINK_OPT} ${CMAKE_COVERAGE_EXE_LINKER_OPTIONS}") else() # not clang, use gcc message("gcc9 not support currently, please set OB_USE_CLANG ON and we will finish it as soon as possible") endif() diff --git a/deps/easy/src/io/easy_baseth_pool.c b/deps/easy/src/io/easy_baseth_pool.c index fa3414461..ed4b0327c 100644 --- a/deps/easy/src/io/easy_baseth_pool.c +++ b/deps/easy/src/io/easy_baseth_pool.c @@ -296,7 +296,7 @@ static void easy_baseth_pool_sighand(int sig, siginfo_t *sinfo, void *ucontext) int i, idx = 0; char _buffer_stack_[512]; - int n = backtrace(array, 25); + int n = ob_backtrace_c(array, 25); if (n > 2) { for (i = 2; i < n; i++) idx += lnprintf(idx + _buffer_stack_, 20, "%p ", array[i]); diff --git a/deps/easy/src/io/easy_log.h b/deps/easy/src/io/easy_log.h index 8c60946b7..3c5ea045e 100644 --- a/deps/easy/src/io/easy_log.h +++ b/deps/easy/src/io/easy_log.h @@ -59,10 +59,8 @@ typedef enum { #define easy_trace_log(format, args...) easy_common_log(EASY_LOG_TRACE, format, ## args) #define SYS_ERROR(format...) easy_error_log(format) // 打印backtrace -#define EASY_PRINT_BT(format, args...) \ - {char _buffer_stack_[256];{void *array[10];int i, idx=0, n = backtrace(array, 10); \ - for (i = 0; i < n; i++) idx += lnprintf(idx+_buffer_stack_, 25, "%p ", array[i]);}\ - easy_log_format(EASY_LOG_OFF, __FILE__, __LINE__, __FUNCTION__, "%s" format, _buffer_stack_, ## args);} +#define EASY_PRINT_BT(format, args...) \ + {easy_log_format(EASY_LOG_OFF, __FILE__, __LINE__, __FUNCTION__, "%s" format, easy_lbt(), ## args);} extern easy_log_level_t easy_log_level; extern easy_log_format_pt easy_log_format; diff --git a/deps/easy/src/util/easy_util.c b/deps/easy/src/util/easy_util.c index 3a78db1b1..502c3ca38 100644 --- a/deps/easy/src/util/easy_util.c +++ b/deps/easy/src/util/easy_util.c @@ -20,29 +20,13 @@ #define USECSTEP 10 #define USECSTART 100 static const double EASY_DOUBLE_EPSINON = 1e-14; -static char *parray(char *buf, int64_t len, int64_t *array, int size) -{ - int64_t pos = 0; - int64_t count = 0; - int64_t i = 0; - for (i = 0; i < size; i++) { - count = snprintf(buf + pos, len - pos, "0x%lx ", array[i]); - if (count >= 0 && pos + count + 1 < len) { - pos += count; - } else { - break; - } - } - buf[pos + 1] = 0; - return buf; -} - +extern char *parray_c(char *buf, int64_t len, int64_t *array, int size); const char *easy_lbt() { static __thread void *addrs[100]; static __thread char buf[1024]; - int size = backtrace(addrs, 100); - return parray(buf, sizeof(buf), (int64_t *)addrs, size); + int size = ob_backtrace_c(addrs, 100); + return parray_c(buf, sizeof(buf), (int64_t *)addrs, size); } const char *easy_lbt_str() @@ -57,7 +41,7 @@ const char *easy_lbt_str() sprintf(buf, "\n"); pos++; - size = backtrace(addrs, 100); + size = ob_backtrace_c(addrs, 100); symbols = backtrace_symbols(addrs, 100); if (NULL == symbols) { return buf; @@ -211,7 +195,7 @@ double easy_get_cpu_mhz(int no_cpu_freq_fail) proc = proc_get_cpu_mhz(no_cpu_freq_fail); easy_debug_log("Got CPU mhz, sample(%lf), proc(%lf).\n", sample, proc); - if ((fabs(proc) < EASY_DOUBLE_EPSINON) || + if ((fabs(proc) < EASY_DOUBLE_EPSINON) || (fabs(sample) < EASY_DOUBLE_EPSINON)) { return 0; } @@ -223,4 +207,3 @@ double easy_get_cpu_mhz(int no_cpu_freq_fail) } return proc; } - diff --git a/deps/easy/src/util/easy_util.h b/deps/easy/src/util/easy_util.h index f673533a3..8cacabfa4 100644 --- a/deps/easy/src/util/easy_util.h +++ b/deps/easy/src/util/easy_util.h @@ -15,6 +15,7 @@ #include "easy_define.h" +extern int ob_backtrace_c(void **buffer, int size); const char* easy_lbt(); const char* easy_lbt_str(); const char* easy_get_func_name(void *addr); diff --git a/deps/oblib/src/lib/CMakeLists.txt b/deps/oblib/src/lib/CMakeLists.txt index e87fbe14a..2ae3bee4f 100644 --- a/deps/oblib/src/lib/CMakeLists.txt +++ b/deps/oblib/src/lib/CMakeLists.txt @@ -225,6 +225,7 @@ ob_set_subtarget(oblib_lib utility utility/ob_tracepoint.cpp utility/ob_utility.cpp utility/utility.cpp + utility/ob_backtrace.cpp utility/ob_proto_trans_util.cpp ) diff --git a/deps/oblib/src/lib/alloc/memory_sanity.cpp b/deps/oblib/src/lib/alloc/memory_sanity.cpp index 444499fdc..0eee5ccd4 100644 --- a/deps/oblib/src/lib/alloc/memory_sanity.cpp +++ b/deps/oblib/src/lib/alloc/memory_sanity.cpp @@ -53,7 +53,7 @@ void memory_sanity_abort() abort(); } void *addrs[128]; - int n_addr = backtrace(addrs, sizeof(addrs)/sizeof(addrs[0])); + int n_addr = ob_backtrace(addrs, sizeof(addrs)/sizeof(addrs[0])); void *vip_addr = NULL; for (int i = 0; NULL == vip_addr && i < n_addr; i++) { for (int j = 0; NULL == vip_addr && j < sizeof(vips)/sizeof(vips[0]); j++) { @@ -71,7 +71,7 @@ void memory_sanity_abort() if (vip_addr != NULL) { if (REACH_TIME_INTERVAL(1000 * 1000)) { fprintf(stderr, "[ERROR] sanity check failed, vip_addr: %p, lbt: %s\n", - vip_addr, oceanbase::common::lbt(addrs, n_addr)); + vip_addr, oceanbase::common::parray((int64_t*)addrs, n_addr)); } } else { char buf[8192]; @@ -103,7 +103,7 @@ void memory_sanity_abort() oceanbase::common::backtrace_symbolize(addrs, n_addr, check_vip); while (pos > 0 && '\n' == buf[pos - 1]) pos--; fprintf(stderr, "[ERROR] sanity check failed, vip_func: %s, lbt: %s\nsymbolize:\n%.*s\n", vip_func, - oceanbase::common::lbt(addrs, n_addr), pos, buf); + oceanbase::common::parray((int64_t*)addrs, n_addr), pos, buf); if ('\0' == vip_func[0]) { abort(); } diff --git a/deps/oblib/src/lib/alloc/ob_malloc_sample_struct.h b/deps/oblib/src/lib/alloc/ob_malloc_sample_struct.h index 448bbc67c..c602a52f5 100644 --- a/deps/oblib/src/lib/alloc/ob_malloc_sample_struct.h +++ b/deps/oblib/src/lib/alloc/ob_malloc_sample_struct.h @@ -158,8 +158,8 @@ inline bool ObMallocSampleKey::operator==(const ObMallocSampleKey &other) const #define ob_malloc_sample_backtrace(obj, size) \ { \ if (OB_UNLIKELY(obj->on_malloc_sample_)) { \ - void *addrs[100]; \ - int bt_len = backtrace(addrs, ARRAYSIZEOF(addrs)); \ + void *addrs[100]; \ + int bt_len = OB_BACKTRACE_M(addrs, ARRAYSIZEOF(addrs)); \ MEMCPY(&obj->data_[size], (char*)addrs, AOBJECT_BACKTRACE_SIZE); \ if (AOBJECT_BACKTRACE_COUNT > bt_len) { \ reinterpret_cast(obj->data_[size + bt_len * sizeof(void*)]) = nullptr; \ diff --git a/deps/oblib/src/lib/allocator/ob_tc_malloc.cpp b/deps/oblib/src/lib/allocator/ob_tc_malloc.cpp index 22c459734..f5f08398c 100644 --- a/deps/oblib/src/lib/allocator/ob_tc_malloc.cpp +++ b/deps/oblib/src/lib/allocator/ob_tc_malloc.cpp @@ -142,6 +142,7 @@ void __attribute__((constructor(MALLOC_INIT_PRIORITY))) init_global_memory_pool #ifndef OB_USE_ASAN abort_unless(OB_SUCCESS == install_ob_signal_handler()); #endif + init_proc_map_info(); } int64_t get_virtual_memory_used(int64_t *resident_size) diff --git a/deps/oblib/src/lib/signal/ob_libunwind.c b/deps/oblib/src/lib/signal/ob_libunwind.c index 568ec6689..9e8d93f7f 100644 --- a/deps/oblib/src/lib/signal/ob_libunwind.c +++ b/deps/oblib/src/lib/signal/ob_libunwind.c @@ -34,6 +34,7 @@ int safe_backtrace(char *buf, int64_t len, int64_t *pos) return ret; } +extern int64_t get_rel_offset_c(int64_t addr); static int safe_backtrace_(unw_context_t *context, char *buf, int64_t len, int64_t *pos) { @@ -46,7 +47,8 @@ static int safe_backtrace_(unw_context_t *context, char *buf, int64_t len, ret = -1; } else { for (int i = 0; i < n; i++) { - int count = safe_snprintf(buf + *pos, len - *pos, "0x%lx", addrs[i]); + int64_t addr = get_rel_offset_c(addrs[i]); + int count = safe_snprintf(buf + *pos, len - *pos, "0x%lx", addr); count++; // for space if (count > 0 && *pos + count < len) { *pos += count; diff --git a/deps/oblib/src/lib/utility/ob_backtrace.cpp b/deps/oblib/src/lib/utility/ob_backtrace.cpp new file mode 100644 index 000000000..cda003682 --- /dev/null +++ b/deps/oblib/src/lib/utility/ob_backtrace.cpp @@ -0,0 +1,186 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX LIB + +#include "lib/utility/ob_backtrace.h" +#include +#include +#include +#include +#include +#include "lib/utility/ob_defer.h" +#include "lib/utility/ob_macro_utils.h" +#include "lib/coro/co_var.h" + +namespace oceanbase +{ +namespace common +{ + +int ob_backtrace(void **buffer, int size) +{ + int rv = 0; + if (OB_LIKELY(g_enable_backtrace)) { + rv = backtrace(buffer, size); + } + return rv; +} + +bool read_codesegment_addr_range(int64_t &start_addr, int64_t &end_addr) +{ + bool bret = false; + char fn[64]; + snprintf(fn, sizeof(fn), "/proc/%d/maps", getpid()); + FILE *map_file = fopen(fn, "rt"); + if (!map_file) return bret; + DEFER(fclose(map_file)); + char buff[1024]; + while (fgets(buff, sizeof buff, map_file) != NULL) { + int len = strlen(buff); + if (len > 0 && buff[len-1] == '\n') { + buff[--len] = '\0'; + } + char* tokens[8]; + int n_token = 0; + for (char *saveptr = NULL, *value = strtok_r(buff, " ", &saveptr); + NULL != value && n_token < ARRAYSIZEOF(tokens); + value = strtok_r(NULL, " ", &saveptr)) { + tokens[n_token++] = value; + } + if (n_token < 6) { + continue; + } + char *perms = tokens[1]; + if (strlen(perms) == 4 && perms[2] != 'x') { + continue; + } + int64_t a0 = 0, a1 = 0; + sscanf(tokens[0], "%lx-%lx", &a0, &a1); + char *path = tokens[5]; + if (path[0] == '[') { + continue; + } + int64_t addr = (int64_t)__func__; + if (addr >= a0 && addr < a1) { + start_addr = a0; + end_addr = a1; + bret = true; + break; + } + } + return bret; +} + +bool g_enable_backtrace = true; +bool g_use_rel_offset = false; +struct ProcMapInfo +{ + int64_t code_start_addr_; + int64_t code_end_addr_; + bool is_inited_; +}; + +ProcMapInfo g_proc_map_info{.code_start_addr_ = -1, .code_end_addr_ = -1, .is_inited_ = false}; + +void init_proc_map_info() +{ + read_codesegment_addr_range(g_proc_map_info.code_start_addr_, g_proc_map_info.code_end_addr_); + g_proc_map_info.is_inited_ = true; +} + +int64_t get_rel_offset(int64_t addr) +{ + if (g_use_rel_offset) { + int64_t code_start_addr = -1; + int64_t code_end_addr = -1; + if (OB_UNLIKELY(!g_proc_map_info.is_inited_)) { + read_codesegment_addr_range(code_start_addr, code_end_addr); + } else { + code_start_addr = g_proc_map_info.code_start_addr_; + code_end_addr = g_proc_map_info.code_end_addr_; + } + if (code_start_addr != -1) { + if (OB_LIKELY(addr >= code_start_addr && addr < code_end_addr)) { + addr -= code_start_addr; + } + } + } + return addr; +} + + +constexpr int MAX_ADDRS_COUNT = 100; +using PointerBuf = void *[MAX_ADDRS_COUNT]; +RLOCAL(PointerBuf, addrs); +RLOCAL(ByteBuf, buffer); + +char *lbt() +{ + int size = OB_BACKTRACE_M(addrs, MAX_ADDRS_COUNT); + return parray(*&buffer, LBT_BUFFER_LENGTH, (int64_t *)addrs, size); +} + +char *lbt(char *buf, int32_t len) +{ + int size = OB_BACKTRACE_M(addrs, MAX_ADDRS_COUNT); + return parray(buf, len, (int64_t *)addrs, size); +} + +char *parray(int64_t *array, int size) +{ + return parray(buffer, LBT_BUFFER_LENGTH, array, size); +} + +char *parray(char *buf, int64_t len, int64_t *array, int size) +{ + //As used in lbt, and lbt used when print error log. + //Can not print error log this function. + if (NULL != buf && len > 0 && NULL != array) { + int64_t pos = 0; + int64_t count = 0; + for (int64_t i = 0; i < size; i++) { + int64_t addr = get_rel_offset(array[i]); + if (0 == i) { + count = snprintf(buf + pos, len - pos, "0x%lx", addr); + } else { + count = snprintf(buf + pos, len - pos, " 0x%lx", addr); + } + if (count >= 0 && pos + count < len) { + pos += count; + } else { + // buf not enough + break; + } + } + buf[pos] = 0; + } + return buf; +} + +EXTERN_C_BEGIN +int ob_backtrace_c(void **buffer, int size) +{ + return OB_BACKTRACE_M(buffer, size); +} +char *parray_c(char *buf, int64_t len, int64_t *array, int size) +{ + return parray(buf, len, array, size); +} +int64_t get_rel_offset_c(int64_t addr) +{ + return get_rel_offset(addr); +} +EXTERN_C_END + +} // end namespace common +} // end namespace oceanbase diff --git a/deps/oblib/src/lib/utility/ob_backtrace.h b/deps/oblib/src/lib/utility/ob_backtrace.h new file mode 100644 index 000000000..69b797316 --- /dev/null +++ b/deps/oblib/src/lib/utility/ob_backtrace.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_COMMON_OB_BACKTRACE_H_ +#define OCEANBASE_COMMON_OB_BACKTRACE_H_ + +#include +namespace oceanbase +{ +namespace common +{ +void init_proc_map_info(); +extern bool g_enable_backtrace; +extern bool g_use_rel_offset; +const int64_t LBT_BUFFER_LENGTH = 1024; +int ob_backtrace(void **buffer, int size); +// save one layer of call stack +#define OB_BACKTRACE_M(buffer, size) \ + ({ \ + int rv = 0; \ + if (OB_LIKELY(::oceanbase::common::g_enable_backtrace)) { \ + rv = backtrace(buffer, size); \ + } \ + rv; \ + }) +char *lbt(); +char *lbt(char *buf, int32_t len); +char *parray(int64_t *array, int size); +char *parray(char *buf, int64_t len, int64_t *array, int size); +} // end namespace common +} // end namespace oceanbase + +#endif //OCEANBASE_COMMON_OB_BACKTRACE_H_ diff --git a/deps/oblib/src/lib/utility/ob_preload.h b/deps/oblib/src/lib/utility/ob_preload.h index 3f9882fdb..1feb2d7dc 100644 --- a/deps/oblib/src/lib/utility/ob_preload.h +++ b/deps/oblib/src/lib/utility/ob_preload.h @@ -26,7 +26,7 @@ inline int64_t &bt(const char *msg) static int64_t enable_bt = 0; if (enable_bt > 0) { void *buffer[100]; - int size = backtrace(buffer, 100); + int size = ob_backtrace(buffer, 100); char **strings = backtrace_symbols(buffer, size); _OB_LOG(DEBUG, "%s", msg); if (NULL != strings) { diff --git a/deps/oblib/src/lib/utility/utility.cpp b/deps/oblib/src/lib/utility/utility.cpp index 34185e8a5..6ae315233 100644 --- a/deps/oblib/src/lib/utility/utility.cpp +++ b/deps/oblib/src/lib/utility/utility.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX LIB #include "dirent.h" +#include #include "lib/utility/utility.h" #include "lib/ob_define.h" #include "util/easy_inet.h" @@ -37,52 +38,6 @@ extern "C" void do_breakpad_init() {} } -char *parray(char *buf, int64_t len, int64_t *array, int size) -{ - //As used in lbt, and lbt used when print error log. - //Can not print error log this function. - if (NULL != buf && len > 0 && NULL != array) { - int64_t pos = 0; - int64_t count = 0; - for (int64_t i = 0; i < size; i++) { - if (0 == i) { - count = snprintf(buf + pos, len - pos, "0x%lx", array[i]); - } else { - count = snprintf(buf + pos, len - pos, " 0x%lx", array[i]); - } - if (count >= 0 && pos + count < len) { - pos += count; - } else { - // buf not enough - break; - } - } - buf[pos] = 0; - } - return buf; -} - -constexpr int MAX_ADDRS_COUNT = 100; -using PointerBuf = void *[MAX_ADDRS_COUNT]; -RLOCAL(PointerBuf, addrs); -RLOCAL(ByteBuf, buffer); - -char *lbt() -{ - int size = backtrace(addrs, MAX_ADDRS_COUNT); - return parray(*&buffer, LBT_BUFFER_LENGTH, (int64_t *)*&addrs, size); -} - -char *lbt(char *buf, int32_t len) -{ - int size = backtrace(addrs, MAX_ADDRS_COUNT); - return parray(buf, len, (int64_t *)*&addrs, size); -} - -char *lbt(void **addrs, int32_t size) -{ - return parray(*&buffer, LBT_BUFFER_LENGTH, (int64_t *)*&addrs, size); -} void hex_dump(const void *data, const int32_t size, const bool char_type /*= true*/, const int32_t log_level /*= OB_LOG_LEVEL_DEBUG*/) diff --git a/deps/oblib/src/lib/utility/utility.h b/deps/oblib/src/lib/utility/utility.h index d420aa8e4..463ee20f8 100644 --- a/deps/oblib/src/lib/utility/utility.h +++ b/deps/oblib/src/lib/utility/utility.h @@ -22,6 +22,7 @@ #include "lib/stat/ob_diagnose_info.h" #include "lib/utility/ob_print_utils.h" #include "lib/utility/ob_utility.h" +#include "lib/utility/ob_backtrace.h" #include "lib/oblog/ob_trace_log.h" #include "lib/container/ob_iarray.h" @@ -63,11 +64,6 @@ struct ObObj; class ObObjParam; class ObAddr; -const int64_t LBT_BUFFER_LENGTH = 1024; -char *parray(char *buf, int64_t len, int64_t *array, int size); -char *lbt(); -char *lbt(char *buf, int32_t len); -char *lbt(void **addrs, int32_t size); void hex_dump(const void *data, const int32_t size, const bool char_type = true, const int32_t log_level = OB_LOG_LEVEL_DEBUG); int32_t parse_string_to_int_array(const char *line, diff --git a/deps/oblib/src/rpc/frame/ob_net_easy.cpp b/deps/oblib/src/rpc/frame/ob_net_easy.cpp index 6582bb110..733570897 100644 --- a/deps/oblib/src/rpc/frame/ob_net_easy.cpp +++ b/deps/oblib/src/rpc/frame/ob_net_easy.cpp @@ -579,6 +579,14 @@ int ObNetEasy::load_ssl_config(const bool use_bkmi, return ret; } +template +void do_not_optimize(T const& value) +{ + asm volatile("" : : "g"(value) : "memory"); +} + +// If there is a hang problem in the lbt, +// you can use the disaster recovery capability of the observer to switch traffic static void rpc_easy_timer_cb(EV_P_ ev_timer *w, int revents) { UNUSED(loop); @@ -636,6 +644,17 @@ static void batch_rpc_easy_timer_cb(EV_P_ ev_timer *w, int revents) } } +#define DEFINE_CB_WITH_LBT(cb) \ +static void cb##_with_lbt(EV_P_ ev_timer *w, int revents) \ +{ \ + do_not_optimize(lbt()); \ + cb(loop, w, revents); \ +} + +DEFINE_CB_WITH_LBT(rpc_easy_timer_cb) +DEFINE_CB_WITH_LBT(high_prio_rpc_easy_timer_cb) +DEFINE_CB_WITH_LBT(batch_rpc_easy_timer_cb) + static void mysql_easy_timer_cb(EV_P_ ev_timer *w, int revents) { UNUSED(loop); @@ -710,7 +729,7 @@ int ObNetEasy::init(const ObNetOptions &opts, uint8_t negotiation_enable) { if (!OB_ISNULL(ioth)) { ev_timer_init(&ioth->user_timer, - rpc_easy_timer_cb, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); + rpc_easy_timer_cb_with_lbt, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); ev_timer_start(ioth->loop, &(ioth->user_timer)); } } @@ -721,7 +740,7 @@ int ObNetEasy::init(const ObNetOptions &opts, uint8_t negotiation_enable) { if (!OB_ISNULL(ioth)) { ev_timer_init(&ioth->user_timer, - high_prio_rpc_easy_timer_cb, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); + high_prio_rpc_easy_timer_cb_with_lbt, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); ev_timer_start(ioth->loop, &(ioth->user_timer)); } } @@ -732,7 +751,7 @@ int ObNetEasy::init(const ObNetOptions &opts, uint8_t negotiation_enable) { if (!OB_ISNULL(ioth)) { ev_timer_init(&ioth->user_timer, - batch_rpc_easy_timer_cb, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); + batch_rpc_easy_timer_cb_with_lbt, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); ev_timer_start(ioth->loop, &(ioth->user_timer)); } } @@ -766,7 +785,7 @@ int ObNetEasy::init(const ObNetOptions &opts, uint8_t negotiation_enable) { if (!OB_ISNULL(ioth)) { ev_timer_init(&ioth->user_timer, - rpc_easy_timer_cb, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); + rpc_easy_timer_cb_with_lbt, EASY_STAT_INTERVAL, EASY_STAT_INTERVAL); ev_timer_start(ioth->loop, &(ioth->user_timer)); } } diff --git a/src/logservice/libobcdc/src/ob_log_utils.cpp b/src/logservice/libobcdc/src/ob_log_utils.cpp index 6946e5db1..4cf48b3a7 100644 --- a/src/logservice/libobcdc/src/ob_log_utils.cpp +++ b/src/logservice/libobcdc/src/ob_log_utils.cpp @@ -1310,7 +1310,7 @@ char *lbt_oblog() //in this function and functions called. static __thread void *addrs[100]; static __thread char buf[LBT_BUFFER_LENGTH]; - int size = backtrace(addrs, 100); + int size = ob_backtrace(addrs, 100); char **res = backtrace_symbols(addrs, 100); int64_t pos = 0; diff --git a/src/observer/main.cpp b/src/observer/main.cpp index 7b80bdb81..f72beeb27 100644 --- a/src/observer/main.cpp +++ b/src/observer/main.cpp @@ -406,6 +406,7 @@ int main(int argc, char *argv[]) snprintf(ob_get_tname(), OB_THREAD_NAME_BUF_LEN, "observer"); } ObStackHeaderGuard stack_header_guard; + g_use_rel_offset = true; #ifndef OB_USE_ASAN init_malloc_hook(); #endif diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index 59000a092..e35781ff1 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -201,7 +201,7 @@ int ObInnerSQLConnection::init(ObInnerSQLConnectionPool *pool, tid_ = GETTID(); if (NULL == extern_session || 0 != EVENT_CALL(EventTable::EN_INNER_SQL_CONN_LEAK_CHECK)) { // Only backtrace internal used connection to avoid performance problems. - bt_size_ = backtrace(bt_addrs_, MAX_BT_SIZE); + bt_size_ = ob_backtrace(bt_addrs_, MAX_BT_SIZE); } config_ = config; associated_client_ = client_addr; @@ -2317,13 +2317,7 @@ void ObInnerSQLConnection::dump_conn_bt_info() int64_t pos = 0; (void)ObTimeUtility2::usec_to_str(init_timestamp_, buf_time, OB_MAX_TIMESTAMP_LENGTH, pos); pos = 0; - for (int i = 0; i < bt_size_; ++i) { - if (OB_UNLIKELY(pos + 1 > BUF_SIZE)) { - LOG_WARN_RET(OB_ERR_UNEXPECTED, "buf is not large enough", K(pos), K(BUF_SIZE)); - } else { - (void)databuff_printf(buf_bt, BUF_SIZE, pos, "%p ", bt_addrs_[i]); - } - } + parray(buf_bt, BUF_SIZE, (int64_t*)*&bt_addrs_, bt_size_); LOG_WARN_RET(OB_SUCCESS, "dump inner sql connection backtrace", "tid", tid_, "init time", buf_time, "backtrace", buf_bt); } diff --git a/src/observer/ob_server_reload_config.cpp b/src/observer/ob_server_reload_config.cpp index b63ee89d5..9517bac23 100644 --- a/src/observer/ob_server_reload_config.cpp +++ b/src/observer/ob_server_reload_config.cpp @@ -298,6 +298,10 @@ int ObServerReloadConfig::operator()() { ObSysVariables::set_value("datadir", GCONF.data_dir); } + + { + common::g_enable_backtrace = GCONF._enable_backtrace_function; + } return real_ret; } diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 02d4e93f9..1afc6c032 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1416,3 +1416,6 @@ DEF_INT(_pipelined_table_function_memory_limit, OB_TENANT_PARAMETER, "524288000" DEF_BOOL(_enable_reserved_user_dcl_restriction, OB_CLUSTER_PARAMETER, "False", "specifies whether to forbid non-reserved user to modify reserved users", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_BOOL(_enable_backtrace_function, OB_CLUSTER_PARAMETER, "True", + "Decide whether to let the backtrace function take effect", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 3a47de4df..85772e2f7 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -244,6 +244,7 @@ _chunk_row_store_mem_limit _ctx_memory_limit _data_storage_io_timeout _enable_adaptive_compaction +_enable_backtrace_function _enable_block_file_punch_hole _enable_compaction_diagnose _enable_convert_real_to_decimal diff --git a/unittest/share/test_json_path.cpp b/unittest/share/test_json_path.cpp index 026043dbb..92d02c745 100644 --- a/unittest/share/test_json_path.cpp +++ b/unittest/share/test_json_path.cpp @@ -187,7 +187,7 @@ TEST_F(TestJsonPath, test_parse_array_node) ObArenaAllocator allocator(ObModIds::TEST); ObJsonPath test_path1("$[ * ]", &allocator); test_path1.index_ = 1; - + ret = test_path1.parse_single_array_node(); ASSERT_EQ(1, test_path1.path_node_cnt()); ASSERT_EQ(ret, OB_SUCCESS); @@ -683,7 +683,8 @@ TEST_F(TestJsonPath, test_member_node) // 只有一个节点 ASSERT_EQ(1, test_path.path_node_cnt()); ASSERT_EQ(JPN_MEMBER,test_path.path_nodes_[0]->get_node_type()); - ObString str(test_path.path_nodes_[0]->get_node_content().member_.object_name_); + const auto &member = test_path.path_nodes_[0]->get_node_content().member_; + ObString str(member.len_, member.object_name_); ASSERT_TRUE(str.case_compare("name") == 0); std::cout<get_node_content().member_.object_name_<get_node_content().array_range_.is_first_index_from_end_); ASSERT_EQ(1,test_path.path_nodes_[i]->get_node_content().array_range_.last_index_); ASSERT_EQ(true,test_path.path_nodes_[i]->get_node_content().array_range_.is_last_index_from_end_); - + } } } else { @@ -875,27 +876,27 @@ TEST_F(TestJsonPath, test_random) // 添加 JPN_MEMBER_WILDCARD str.append(".*"); break; - + case 2: // JPN_ARRAY_CELL str.append("[last-5]"); break; - + case 3: // JPN_ARRAY_RANGE str.append("[10 to last-1]"); break; - + case 4: // JPN_ARRAY_CELL_WILDCARD str.append("[*]"); break; - + case 5: // JPN_WILDCARD_ELLIPSIS str.append("**"); break; - + default: break; } @@ -906,7 +907,7 @@ TEST_F(TestJsonPath, test_random) int ret = OB_SUCCESS; ObString str_origin(str.ptr()); std::cout<get_node_type()<get_node_content().array_cell_.is_index_from_end_<