Commit dfe659ba authored by gejun's avatar gejun

Work around the issue on fedora 26 that weak impl. of MallocExtension::instance…

Work around the issue on fedora 26 that weak impl. of MallocExtension::instance is not overriden by tcmalloc & Macro BAIDU_RPC_ENABLE_HEAP_PROFILER is not needed anymore
parent 887fc474
...@@ -6,7 +6,7 @@ include $(BRPC_PATH)/config.mk ...@@ -6,7 +6,7 @@ include $(BRPC_PATH)/config.mk
# 2. Added -D__const__= : Avoid over-optimizations of TLS variables by GCC>=4.8 # 2. Added -D__const__= : Avoid over-optimizations of TLS variables by GCC>=4.8
CXXFLAGS = -std=c++0x -g -DNDEBUG -O2 -D__const__= -pipe -W -Wall -Werror -Wno-unused-parameter -fPIC -fno-omit-frame-pointer CXXFLAGS = -std=c++0x -g -DNDEBUG -O2 -D__const__= -pipe -W -Wall -Werror -Wno-unused-parameter -fPIC -fno-omit-frame-pointer
ifeq ($(NEED_GPERFTOOLS), 1) ifeq ($(NEED_GPERFTOOLS), 1)
CXXFLAGS+=-DBRPC_ENABLE_CPU_PROFILER -DBRPC_ENABLE_HEAP_PROFILER CXXFLAGS+=-DBRPC_ENABLE_CPU_PROFILER
endif endif
HDRS+=$(BRPC_PATH)/output/include HDRS+=$(BRPC_PATH)/output/include
LIBS+=$(BRPC_PATH)/output/lib LIBS+=$(BRPC_PATH)/output/lib
......
...@@ -6,7 +6,7 @@ include $(BRPC_PATH)/config.mk ...@@ -6,7 +6,7 @@ include $(BRPC_PATH)/config.mk
# 2. Added -D__const__= : Avoid over-optimizations of TLS variables by GCC>=4.8 # 2. Added -D__const__= : Avoid over-optimizations of TLS variables by GCC>=4.8
CXXFLAGS = -std=c++0x -g -DNDEBUG -O2 -D__const__= -pipe -W -Wall -Werror -Wno-unused-parameter -fPIC -fno-omit-frame-pointer CXXFLAGS = -std=c++0x -g -DNDEBUG -O2 -D__const__= -pipe -W -Wall -Werror -Wno-unused-parameter -fPIC -fno-omit-frame-pointer
ifeq ($(NEED_GPERFTOOLS), 1) ifeq ($(NEED_GPERFTOOLS), 1)
CXXFLAGS += -DBRPC_ENABLE_CPU_PROFILER -DBRPC_ENABLE_HEAP_PROFILER CXXFLAGS += -DBRPC_ENABLE_CPU_PROFILER
endif endif
HDRS+=$(BRPC_PATH)/output/include HDRS+=$(BRPC_PATH)/output/include
LIBS+=$(BRPC_PATH)/output/lib LIBS+=$(BRPC_PATH)/output/lib
......
...@@ -40,7 +40,6 @@ void ContentionProfilerStop(); ...@@ -40,7 +40,6 @@ void ContentionProfilerStop();
namespace brpc { namespace brpc {
extern bool cpu_profiler_enabled; extern bool cpu_profiler_enabled;
extern bool heap_profiler_enabled;
DEFINE_int32(max_profiling_seconds, 300, "upper limit of running time of profilers"); DEFINE_int32(max_profiling_seconds, 300, "upper limit of running time of profilers");
BRPC_VALIDATE_GFLAG(max_profiling_seconds, NonNegativeInteger); BRPC_VALIDATE_GFLAG(max_profiling_seconds, NonNegativeInteger);
...@@ -661,9 +660,12 @@ static void DoProfiling(ProfilingType type, ...@@ -661,9 +660,12 @@ static void DoProfiling(ProfilingType type,
bthread::ContentionProfilerStop(); bthread::ContentionProfilerStop();
} else if (type == PROFILING_HEAP) { } else if (type == PROFILING_HEAP) {
MallocExtension* malloc_ext = MallocExtension::instance(); MallocExtension* malloc_ext = MallocExtension::instance();
if (malloc_ext == NULL) { if (malloc_ext == NULL || !has_TCMALLOC_SAMPLE_PARAMETER()) {
os << "Heap profiler is not enabled" os << "Heap profiler is not enabled";
<< (use_html ? "</body></html>" : "\n"); if (malloc_ext != NULL) {
os << " (no TCMALLOC_SAMPLE_PARAMETER in env)";
}
os << '.' << (use_html ? "</body></html>" : "\n");
os.move_to(resp); os.move_to(resp);
cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN); cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN);
return NotifyWaiters(type, cntl, view); return NotifyWaiters(type, cntl, view);
...@@ -681,7 +683,7 @@ static void DoProfiling(ProfilingType type, ...@@ -681,7 +683,7 @@ static void DoProfiling(ProfilingType type,
} else if (type == PROFILING_GROWTH) { } else if (type == PROFILING_GROWTH) {
MallocExtension* malloc_ext = MallocExtension::instance(); MallocExtension* malloc_ext = MallocExtension::instance();
if (malloc_ext == NULL) { if (malloc_ext == NULL) {
os << "Growth profiler is not enabled" os << "Growth profiler is not enabled."
<< (use_html ? "</body></html>" : "\n"); << (use_html ? "</body></html>" : "\n");
os.move_to(resp); os.move_to(resp);
cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN); cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN);
...@@ -726,20 +728,27 @@ static void StartProfiling(ProfilingType type, ...@@ -726,20 +728,27 @@ static void StartProfiling(ProfilingType type,
const bool use_html = UseHTML(cntl->http_request()); const bool use_html = UseHTML(cntl->http_request());
butil::IOBufBuilder os; butil::IOBufBuilder os;
bool enabled = false; bool enabled = false;
const char* extra_desc = "";
if (type == PROFILING_CPU) { if (type == PROFILING_CPU) {
enabled = cpu_profiler_enabled; enabled = cpu_profiler_enabled;
} else if (type == PROFILING_CONTENTION) { } else if (type == PROFILING_CONTENTION) {
enabled = true; enabled = true;
} else if (type == PROFILING_HEAP || type == PROFILING_GROWTH) { } else if (type == PROFILING_HEAP) {
enabled = heap_profiler_enabled; enabled = IsHeapProfilerEnabled();
if (enabled && !has_TCMALLOC_SAMPLE_PARAMETER()) {
enabled = false;
extra_desc = " (no TCMALLOC_SAMPLE_PARAMETER in env)";
}
} else if (type == PROFILING_GROWTH) {
enabled = IsHeapProfilerEnabled();
} }
const char* const type_str = ProfilingType2String(type); const char* const type_str = ProfilingType2String(type);
if (!use_html) { if (!use_html) {
if (!enabled) { if (!enabled) {
os << "Error: " << type_str << " profiler is not enabled yet.\n" os << "Error: " << type_str << " profiler is not enabled."
"To enable all profilers, link tcmalloc and define macros BRPC_ENABLE_CPU_PROFILER and BRPC_ENABLE_HEAP_PROFILER\n" << extra_desc << "\n"
"Or read the docs: docs/cn/{cpu_profiler.md,heap_profiler.md}\n"; "Read the docs: docs/cn/{cpu_profiler.md,heap_profiler.md}\n";
os.move_to(cntl->response_attachment()); os.move_to(cntl->response_attachment());
cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN); cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN);
return; return;
...@@ -980,10 +989,10 @@ static void StartProfiling(ProfilingType type, ...@@ -980,10 +989,10 @@ static void StartProfiling(ProfilingType type,
if (!enabled && view == NULL) { if (!enabled && view == NULL) {
os << "<p><span style='color:red'>Error:</span> " os << "<p><span style='color:red'>Error:</span> "
<< type_str << " profiler is not enabled yet.</p>" << type_str << " profiler is not enabled." << extra_desc << "</p>"
"<p>To enable all profilers, link tcmalloc and define macros BRPC_ENABLE_CPU_PROFILER and BRPC_ENABLE_HEAP_PROFILER" "<p>To enable all profilers, link tcmalloc and define macros BRPC_ENABLE_CPU_PROFILER"
"</p><p>Or read docs: <a href='https://github.com/brpc/brpc/blob/master/docs/cn/cpu_profiler.md'>cpu_profiler.md</a>" "</p><p>Or read docs: <a href='https://github.com/brpc/brpc/blob/master/docs/cn/cpu_profiler.md'>cpu_profiler</a>"
" and <a href='https://github.com/brpc/brpc/blob/master/docs/cn/heap_profiler.md'>heap_profiler.md</a>" " and <a href='https://github.com/brpc/brpc/blob/master/docs/cn/heap_profiler.md'>heap_profiler</a>"
"</p></body></html>"; "</p></body></html>";
os.move_to(cntl->response_attachment()); os.move_to(cntl->response_attachment());
cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN); cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "brpc/builtin/index_service.h" #include "brpc/builtin/index_service.h"
#include "brpc/builtin/status_service.h" #include "brpc/builtin/status_service.h"
#include "brpc/builtin/common.h" #include "brpc/builtin/common.h"
#include "brpc/details/tcmalloc_extension.h"
namespace brpc { namespace brpc {
...@@ -36,7 +37,6 @@ DECLARE_bool(enable_threads_service); ...@@ -36,7 +37,6 @@ DECLARE_bool(enable_threads_service);
// Set in ProfilerLinker. // Set in ProfilerLinker.
bool cpu_profiler_enabled = false; bool cpu_profiler_enabled = false;
bool heap_profiler_enabled = false;
void IndexService::default_method(::google::protobuf::RpcController* controller, void IndexService::default_method(::google::protobuf::RpcController* controller,
const IndexRequest*, const IndexRequest*,
...@@ -137,10 +137,10 @@ void IndexService::default_method(::google::protobuf::RpcController* controller, ...@@ -137,10 +137,10 @@ void IndexService::default_method(::google::protobuf::RpcController* controller,
<< Path("/hotspots/cpu", html_addr) << " : Profiling CPU" << Path("/hotspots/cpu", html_addr) << " : Profiling CPU"
<< (!cpu_profiler_enabled ? " (disabled)" : "") << NL << (!cpu_profiler_enabled ? " (disabled)" : "") << NL
<< Path("/hotspots/heap", html_addr) << " : Profiling heap" << Path("/hotspots/heap", html_addr) << " : Profiling heap"
<< (!heap_profiler_enabled ? " (disabled)" : "") << NL << (!IsHeapProfilerEnabled() ? " (disabled)" : "") << NL
<< Path("/hotspots/growth", html_addr) << Path("/hotspots/growth", html_addr)
<< " : Profiling growth of heap" << " : Profiling growth of heap"
<< (!heap_profiler_enabled ? " (disabled)" : "") << NL; << (!IsHeapProfilerEnabled() ? " (disabled)" : "") << NL;
} }
os << "curl -H 'Content-Type: application/json' -d 'JSON' " << my_addr os << "curl -H 'Content-Type: application/json' -d 'JSON' " << my_addr
<< "/ServiceName/MethodName : Call method by http+json" << NL << "/ServiceName/MethodName : Call method by http+json" << NL
......
...@@ -207,10 +207,14 @@ void PProfService::heap( ...@@ -207,10 +207,14 @@ void PProfService::heap(
ClosureGuard done_guard(done); ClosureGuard done_guard(done);
Controller* cntl = static_cast<Controller*>(controller_base); Controller* cntl = static_cast<Controller*>(controller_base);
MallocExtension* malloc_ext = MallocExtension::instance(); MallocExtension* malloc_ext = MallocExtension::instance();
if (malloc_ext == NULL) { if (malloc_ext == NULL || !has_TCMALLOC_SAMPLE_PARAMETER()) {
cntl->SetFailed(ENOMETHOD, "%s, to enable heap profiler, check out " const char* extra_desc = "";
"docs/cn/heap_profiler.md", if (malloc_ext != NULL) {
berror(ENOMETHOD)); extra_desc = " (no TCMALLOC_SAMPLE_PARAMETER in env)";
}
cntl->SetFailed(ENOMETHOD, "Heap profiler is not enabled%s,"
"check out http://wiki.baidu.com/display/RPC",
extra_desc);
return; return;
} }
// Log requester // Log requester
......
...@@ -34,7 +34,6 @@ namespace brpc { ...@@ -34,7 +34,6 @@ namespace brpc {
// defined in src/brpc/builtin/index_service.cpp // defined in src/brpc/builtin/index_service.cpp
extern bool cpu_profiler_enabled; extern bool cpu_profiler_enabled;
extern bool heap_profiler_enabled;
// defined in src/brpc/controller.cpp // defined in src/brpc/controller.cpp
extern int PROFILER_LINKER_DUMMY; extern int PROFILER_LINKER_DUMMY;
...@@ -54,10 +53,6 @@ struct ProfilerLinker { ...@@ -54,10 +53,6 @@ struct ProfilerLinker {
ProfilerStart("this_function_should_never_run"); ProfilerStart("this_function_should_never_run");
} }
#endif #endif
#if defined(BRPC_ENABLE_HEAP_PROFILER) || defined(BAIDU_RPC_ENABLE_HEAP_PROFILER)
heap_profiler_enabled = true;
#endif
} }
}; };
......
#include <dlfcn.h> // dlsym
#include <stdlib.h> // getenv
#include "butil/compiler_specific.h" #include "butil/compiler_specific.h"
#include "brpc/details/tcmalloc_extension.h" #include "brpc/details/tcmalloc_extension.h"
namespace {
typedef MallocExtension* (*GetInstanceFn)();
static pthread_once_t g_get_instance_fn_once = PTHREAD_ONCE_INIT;
static GetInstanceFn g_get_instance_fn = NULL;
static void InitGetInstanceFn() {
g_get_instance_fn = (GetInstanceFn)dlsym(
RTLD_NEXT, "_ZN15MallocExtension8instanceEv");
}
} // namespace
MallocExtension* BAIDU_WEAK MallocExtension::instance() { MallocExtension* BAIDU_WEAK MallocExtension::instance() {
// On fedora 26, this weak function is NOT overriden by the one in tcmalloc
// which is dynamically linked.The same issue can't be re-produced in
// Ubuntu and the exact cause is unknown yet. Using dlsym to get the
// function works around the issue right now. Note that we can't use dlsym
// to fully replace the weak-function mechanism since our code are generally
// not compiled with -rdynamic which writes symbols to the table that
// dlsym reads.
pthread_once(&g_get_instance_fn_once, InitGetInstanceFn);
if (g_get_instance_fn) {
return g_get_instance_fn();
}
return NULL; return NULL;
} }
bool IsHeapProfilerEnabled() {
return MallocExtension::instance() != NULL;
}
static bool check_TCMALLOC_SAMPLE_PARAMETER() {
char* str = getenv("TCMALLOC_SAMPLE_PARAMETER");
if (str == NULL) {
return false;
}
char* endptr;
int val = strtol(str, &endptr, 10);
return (*endptr == '\0' && val > 0);
}
bool has_TCMALLOC_SAMPLE_PARAMETER() {
static bool val = check_TCMALLOC_SAMPLE_PARAMETER();
return val;
}
...@@ -311,3 +311,9 @@ class PERFTOOLS_DLL_DECL MallocExtension { ...@@ -311,3 +311,9 @@ class PERFTOOLS_DLL_DECL MallocExtension {
// in the address space size. // in the address space size.
virtual void** ReadHeapGrowthStackTraces(); virtual void** ReadHeapGrowthStackTraces();
}; };
// True iff heap profiler is enabled.
bool IsHeapProfilerEnabled();
// True iff TCMALLOC_SAMPLE_PARAMETER is set in environment.
bool has_TCMALLOC_SAMPLE_PARAMETER();
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#include "brpc/restful.h" #include "brpc/restful.h"
#include "brpc/rtmp.h" #include "brpc/rtmp.h"
#include "brpc/builtin/common.h" // GetProgramName #include "brpc/builtin/common.h" // GetProgramName
#include "brpc/details/tcmalloc_extension.h"
inline std::ostream& operator<<(std::ostream& os, const timeval& tm) { inline std::ostream& operator<<(std::ostream& os, const timeval& tm) {
const char old_fill = os.fill(); const char old_fill = os.fill();
...@@ -207,30 +208,15 @@ static void PrintSupportedCompressions(std::ostream& os, void*) { ...@@ -207,30 +208,15 @@ static void PrintSupportedCompressions(std::ostream& os, void*) {
} }
} }
static bool check_TCMALLOC_SAMPLE_PARAMETER() {
char* str = getenv("TCMALLOC_SAMPLE_PARAMETER");
if (str == NULL) {
return false;
}
char* endptr;
int val = strtol(str, &endptr, 10);
return (*endptr == '\0' && val > 0);
}
static bool has_TCMALLOC_SAMPLE_PARAMETER() {
static bool val = check_TCMALLOC_SAMPLE_PARAMETER();
return val;
}
static void PrintEnabledProfilers(std::ostream& os, void*) { static void PrintEnabledProfilers(std::ostream& os, void*) {
if (cpu_profiler_enabled) { if (cpu_profiler_enabled) {
os << "cpu "; os << "cpu ";
} }
if (heap_profiler_enabled) { if (IsHeapProfilerEnabled()) {
if (has_TCMALLOC_SAMPLE_PARAMETER()) { if (has_TCMALLOC_SAMPLE_PARAMETER()) {
os << "heap "; os << "heap ";
} else { } else {
os << "heap(lack of TCMALLOC_SAMPLE_PARAMETER) "; os << "heap(no TCMALLOC_SAMPLE_PARAMETER in env) ";
} }
} }
os << "contention"; os << "contention";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment