[CP] [CP] fix MemLeak DeadLock
This commit is contained in:
@ -18,6 +18,7 @@ namespace oceanbase
|
|||||||
namespace common
|
namespace common
|
||||||
{
|
{
|
||||||
lib::ObSimpleRateLimiter ObMemLeakChecker::rl_ = {INT64_MAX};
|
lib::ObSimpleRateLimiter ObMemLeakChecker::rl_ = {INT64_MAX};
|
||||||
|
constexpr const char ObMemLeakChecker::MOD_INFO_MAP_STR[];
|
||||||
|
|
||||||
} // end of namespace common
|
} // end of namespace common
|
||||||
} // end of namespace oceanbase
|
} // end of namespace oceanbase
|
||||||
|
|||||||
@ -24,6 +24,7 @@ namespace common
|
|||||||
{
|
{
|
||||||
class ObMemLeakChecker
|
class ObMemLeakChecker
|
||||||
{
|
{
|
||||||
|
static constexpr const char MOD_INFO_MAP_STR[] = "leakInfoMap";
|
||||||
struct PtrKey
|
struct PtrKey
|
||||||
{
|
{
|
||||||
void *ptr_;
|
void *ptr_;
|
||||||
@ -59,7 +60,26 @@ class ObMemLeakChecker
|
|||||||
typedef hash::ObHashMap<PtrKey, Info> mod_alloc_info_t;
|
typedef hash::ObHashMap<PtrKey, Info> mod_alloc_info_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef hash::ObHashMap<Info, std::pair<int64_t, int64_t>> mod_info_map_t;
|
|
||||||
|
class mod_info_map_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef hash::ObHashMap<Info, std::pair<int64_t, int64_t>> hashmap;
|
||||||
|
int create(int64_t bucket_num)
|
||||||
|
{
|
||||||
|
ObMemAttr attr(common::OB_SERVER_TENANT_ID, MOD_INFO_MAP_STR, ObCtxIds::DEFAULT_CTX_ID,
|
||||||
|
lib::OB_HIGH_ALLOC);
|
||||||
|
return map_.create(bucket_num, attr, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashmap *operator->()
|
||||||
|
{
|
||||||
|
return &map_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
hashmap map_;
|
||||||
|
};
|
||||||
|
|
||||||
using TCharArray = char[2 * lib::AOBJECT_LABEL_SIZE + 1];
|
using TCharArray = char[2 * lib::AOBJECT_LABEL_SIZE + 1];
|
||||||
|
|
||||||
ObMemLeakChecker()
|
ObMemLeakChecker()
|
||||||
@ -103,6 +123,8 @@ public:
|
|||||||
if (nullptr == str || 0 == STRLEN(str) || 0 == STRNCMP(str, "NONE", STRLEN("NONE"))) {
|
if (nullptr == str || 0 == STRLEN(str) || 0 == STRNCMP(str, "NONE", STRLEN("NONE"))) {
|
||||||
origin_str_[0] = '\0';
|
origin_str_[0] = '\0';
|
||||||
tmp_ct = NOCHECK;
|
tmp_ct = NOCHECK;
|
||||||
|
} else if (0 == STRNCMP(str, MOD_INFO_MAP_STR, strlen(MOD_INFO_MAP_STR))) {
|
||||||
|
// ensure leak_mod is different from the mod_info_map's label
|
||||||
} else {
|
} else {
|
||||||
STRNCPY(origin_str_, str, sizeof(origin_str_));
|
STRNCPY(origin_str_, str, sizeof(origin_str_));
|
||||||
origin_str_[sizeof(origin_str_) - 1] = '\0';
|
origin_str_[sizeof(origin_str_) - 1] = '\0';
|
||||||
@ -178,7 +200,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_leak_info_map(hash::ObHashMap<Info, std::pair<int64_t, int64_t>> &info_map)
|
int load_leak_info_map(mod_info_map_t &info_map)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
using hashtable = mod_alloc_info_t::hashtable;
|
using hashtable = mod_alloc_info_t::hashtable;
|
||||||
@ -190,14 +212,14 @@ public:
|
|||||||
while (node_it != bucket_it->node_end()) {
|
while (node_it != bucket_it->node_end()) {
|
||||||
std::pair<int64_t, int64_t> item;
|
std::pair<int64_t, int64_t> item;
|
||||||
//_OB_LOG(INFO, "hash value, bt=%s, hash=%lu", it->second.bt_, it->second.hash());
|
//_OB_LOG(INFO, "hash value, bt=%s, hash=%lu", it->second.bt_, it->second.hash());
|
||||||
ret = info_map.get_refactored(node_it->second, item);
|
ret = info_map->get_refactored(node_it->second, item);
|
||||||
if (OB_FAIL(ret) && OB_HASH_NOT_EXIST != ret) {
|
if (OB_FAIL(ret) && OB_HASH_NOT_EXIST != ret) {
|
||||||
_OB_LOG(INFO, "LEAK_CHECKER, ptr=%p bt=%s", node_it->first.ptr_, node_it->second.bt_);
|
_OB_LOG(INFO, "LEAK_CHECKER, ptr=%p bt=%s", node_it->first.ptr_, node_it->second.bt_);
|
||||||
} else {
|
} else {
|
||||||
if (OB_SUCC(ret)) {
|
if (OB_SUCC(ret)) {
|
||||||
item.first += 1;
|
item.first += 1;
|
||||||
item.second += node_it->second.bytes_;
|
item.second += node_it->second.bytes_;
|
||||||
if (OB_FAIL(info_map.set_refactored(node_it->second, item, 1, 0, 1))) {
|
if (OB_FAIL(info_map->set_refactored(node_it->second, item, 1, 0, 1))) {
|
||||||
_OB_LOG(WARN, "failed to aggregate memory size, ret=%d", ret);
|
_OB_LOG(WARN, "failed to aggregate memory size, ret=%d", ret);
|
||||||
} else {
|
} else {
|
||||||
_OB_LOG(DEBUG, "LEAK_CHECKER hash updated");
|
_OB_LOG(DEBUG, "LEAK_CHECKER hash updated");
|
||||||
@ -205,7 +227,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
item.first = 1;
|
item.first = 1;
|
||||||
item.second = node_it->second.bytes_;
|
item.second = node_it->second.bytes_;
|
||||||
if (OB_FAIL(info_map.set_refactored(node_it->second, item, 1, 0, 0))) {
|
if (OB_FAIL(info_map->set_refactored(node_it->second, item, 1, 0, 0))) {
|
||||||
_OB_LOG(WARN, "failed to aggregate memory size, ret=%d", ret);
|
_OB_LOG(WARN, "failed to aggregate memory size, ret=%d", ret);
|
||||||
} else {
|
} else {
|
||||||
_OB_LOG(DEBUG, "LEAK_CHECKER hash inserted");
|
_OB_LOG(DEBUG, "LEAK_CHECKER hash inserted");
|
||||||
@ -220,11 +242,8 @@ public:
|
|||||||
}
|
}
|
||||||
void print()
|
void print()
|
||||||
{
|
{
|
||||||
ObMemAttr attr(common::OB_SERVER_TENANT_ID, "leakInfoMap", ObCtxIds::DEFAULT_CTX_ID,
|
mod_info_map_t tmp_map;
|
||||||
lib::OB_HIGH_ALLOC);
|
int ret = tmp_map.create(10000);
|
||||||
using Hash = hash::ObHashMap<Info, std::pair<int64_t, int64_t>>;
|
|
||||||
Hash tmp_map;
|
|
||||||
int ret = tmp_map.create(10000, attr, attr);
|
|
||||||
if (OB_FAIL(ret)) {
|
if (OB_FAIL(ret)) {
|
||||||
_OB_LOG(ERROR, "failed to create hashmap, err=%d", ret);
|
_OB_LOG(ERROR, "failed to create hashmap, err=%d", ret);
|
||||||
} else if (OB_FAIL(load_leak_info_map(tmp_map))) {
|
} else if (OB_FAIL(load_leak_info_map(tmp_map))) {
|
||||||
@ -232,8 +251,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
_OB_LOG(INFO, "######## LEAK_CHECKER (str = %s)########", origin_str_);
|
_OB_LOG(INFO, "######## LEAK_CHECKER (str = %s)########", origin_str_);
|
||||||
|
|
||||||
Hash::const_iterator jt = tmp_map.begin();
|
mod_info_map_t::hashmap::const_iterator jt = tmp_map->begin();
|
||||||
for (; jt != tmp_map.end(); ++jt)
|
for (; jt != tmp_map->end(); ++jt)
|
||||||
{
|
{
|
||||||
_OB_LOG(INFO, "[LC] bt=%s, count=%ld, bytes=%ld",
|
_OB_LOG(INFO, "[LC] bt=%s, count=%ld, bytes=%ld",
|
||||||
jt->first.bt_, jt->second.first, jt->second.second);
|
jt->first.bt_, jt->second.first, jt->second.second);
|
||||||
|
|||||||
@ -178,7 +178,7 @@ void ObDumpTaskGenerator::dump_memory_leak()
|
|||||||
LOG_WARN("alloc failed", K(ret));
|
LOG_WARN("alloc failed", K(ret));
|
||||||
} else {
|
} else {
|
||||||
common::ObMemLeakChecker::mod_info_map_t tmp_map;
|
common::ObMemLeakChecker::mod_info_map_t tmp_map;
|
||||||
if (OB_FAIL(tmp_map.create(1024, attr, attr))) {
|
if (OB_FAIL(tmp_map.create(1024))) {
|
||||||
LOG_WARN("create map failed", K(ret));
|
LOG_WARN("create map failed", K(ret));
|
||||||
} else if (OB_FAIL(get_mem_leak_checker().load_leak_info_map(tmp_map))) {
|
} else if (OB_FAIL(get_mem_leak_checker().load_leak_info_map(tmp_map))) {
|
||||||
LOG_WARN("load map failed", K(ret));
|
LOG_WARN("load map failed", K(ret));
|
||||||
@ -191,7 +191,7 @@ void ObDumpTaskGenerator::dump_memory_leak()
|
|||||||
get_mem_leak_checker().get_label(),
|
get_mem_leak_checker().get_label(),
|
||||||
get_mem_leak_checker().get_check_type(),
|
get_mem_leak_checker().get_check_type(),
|
||||||
ObTimeUtility::current_time());
|
ObTimeUtility::current_time());
|
||||||
for (auto it = tmp_map.begin(); it != tmp_map.end(); ++it) {
|
for (auto it = tmp_map->begin(); it != tmp_map->end(); ++it) {
|
||||||
pos += snprintf(buf + pos, buf_len - pos, "bt=%s, count=%ld, bytes=%ld\n",
|
pos += snprintf(buf + pos, buf_len - pos, "bt=%s, count=%ld, bytes=%ld\n",
|
||||||
it->first.bt_, it->second.first, it->second.second);
|
it->first.bt_, it->second.first, it->second.second);
|
||||||
if (pos > buf_len / 2) {
|
if (pos > buf_len / 2) {
|
||||||
|
|||||||
@ -62,19 +62,19 @@ int ObMemLeakCheckerInfo::inner_get_next_row(common::ObNewRow *&row)
|
|||||||
if (OB_FAIL(sanity_check())) {
|
if (OB_FAIL(sanity_check())) {
|
||||||
// error
|
// error
|
||||||
} else if (!opened_) {
|
} else if (!opened_) {
|
||||||
int ret = info_map_.create(10000, ObModIds::TEST);
|
int ret = info_map_.create(10000);
|
||||||
if (OB_FAIL(ret)) {
|
if (OB_FAIL(ret)) {
|
||||||
SERVER_LOG(WARN, "failed to create hashmap", K(ret));
|
SERVER_LOG(WARN, "failed to create hashmap", K(ret));
|
||||||
} else if (OB_FAIL(leak_checker_->load_leak_info_map(info_map_))) {
|
} else if (OB_FAIL(leak_checker_->load_leak_info_map(info_map_))) {
|
||||||
SERVER_LOG(WARN, "failed to collection leak info", K(ret));
|
SERVER_LOG(WARN, "failed to collection leak info", K(ret));
|
||||||
} else {
|
} else {
|
||||||
opened_ = true;
|
opened_ = true;
|
||||||
it_ = info_map_.begin();
|
it_ = info_map_->begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OB_SUCC(ret)) {
|
if (OB_SUCC(ret)) {
|
||||||
if (it_ != info_map_.end()) {
|
if (it_ != info_map_->end()) {
|
||||||
if (OB_FAIL(fill_row(row))) {
|
if (OB_FAIL(fill_row(row))) {
|
||||||
SERVER_LOG(WARN, "failed to fill row", K(ret));
|
SERVER_LOG(WARN, "failed to fill row", K(ret));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
bool opened_;
|
bool opened_;
|
||||||
common::ObMemLeakChecker *leak_checker_;
|
common::ObMemLeakChecker *leak_checker_;
|
||||||
common::ObMemLeakChecker::mod_info_map_t::const_iterator it_;
|
common::ObMemLeakChecker::mod_info_map_t::hashmap::const_iterator it_;
|
||||||
common::ObMemLeakChecker::mod_info_map_t info_map_;
|
common::ObMemLeakChecker::mod_info_map_t info_map_;
|
||||||
common::ObAddr *addr_;
|
common::ObAddr *addr_;
|
||||||
uint64_t tenant_id_;
|
uint64_t tenant_id_;
|
||||||
|
|||||||
Reference in New Issue
Block a user