blob: d44884a5fb3fb116e65b29d545e0ab22e41fb9a4 [file] [log] [blame]
diff --git a/src/brpc/builtin/hotspots_service.cpp b/src/brpc/builtin/hotspots_service.cpp
index c7577320..a5575b39 100644
--- a/src/brpc/builtin/hotspots_service.cpp
+++ b/src/brpc/builtin/hotspots_service.cpp
@@ -760,8 +760,7 @@ static void DoProfiling(ProfilingType type,
ProfilerStop();
} else if (type == PROFILING_CONTENTION) {
if (!bthread::ContentionProfilerStart(prof_name)) {
- os << "Another profiler (not via /hotspots/contention) is running, "
- "try again later" << (use_html ? "</body></html>" : "\n");
+ os << "Contention profiler has been disabled by doris\n";
os.move_to(resp);
cntl->http_response().set_status_code(HTTP_STATUS_SERVICE_UNAVAILABLE);
return NotifyWaiters(type, cntl, view);
@@ -855,6 +854,12 @@ static void StartProfiling(ProfilingType type,
enabled = IsHeapProfilerEnabled();
}
const char* const type_str = ProfilingType2String(type);
+ if (type == PROFILING_CONTENTION) {
+ os << "Error: " << type_str << " profiler is disabled by doris.\n";
+ os.move_to(cntl->response_attachment());
+ cntl->http_response().set_status_code(HTTP_STATUS_SERVICE_UNAVAILABLE);
+ return;
+ }
#if defined(OS_MACOSX)
if (!has_GOOGLE_PPROF_BINARY_PATH()) {
diff --git a/src/brpc/builtin/pprof_service.cpp b/src/brpc/builtin/pprof_service.cpp
index eba71377..48fa5560 100644
--- a/src/brpc/builtin/pprof_service.cpp
+++ b/src/brpc/builtin/pprof_service.cpp
@@ -188,7 +188,7 @@ void PProfService::contention(
return;
}
if (!bthread::ContentionProfilerStart(prof_name)) {
- cntl->SetFailed(EAGAIN, "Another profiler is running, try again later");
+ cntl->SetFailed(EAGAIN, "Contention profiler has been disabled by doris");
return;
}
if (bthread_usleep(sleep_sec * 1000000L) != 0) {
diff --git a/src/bthread/mutex.cpp b/src/bthread/mutex.cpp
index 3d38ef93..aad189bc 100644
--- a/src/bthread/mutex.cpp
+++ b/src/bthread/mutex.cpp
@@ -305,6 +305,8 @@ static int64_t get_nconflicthash(void*) {
// Start profiling contention.
bool ContentionProfilerStart(const char* filename) {
+ LOG(ERROR) << "Contention profiler is disabled by doris.";
+ return false;
if (filename == NULL) {
LOG(ERROR) << "Parameter [filename] is NULL";
return false;
@@ -364,77 +366,79 @@ make_contention_site_invalid(bthread_contention_site_t* cs) {
cs->sampling_range = 0;
}
-// Replace pthread_mutex_lock and pthread_mutex_unlock:
-// First call to sys_pthread_mutex_lock sets sys_pthread_mutex_lock to the
-// real function so that next calls go to the real function directly. This
-// technique avoids calling pthread_once each time.
-typedef int (*MutexOp)(pthread_mutex_t*);
-int first_sys_pthread_mutex_lock(pthread_mutex_t* mutex);
-int first_sys_pthread_mutex_unlock(pthread_mutex_t* mutex);
-static MutexOp sys_pthread_mutex_lock = first_sys_pthread_mutex_lock;
-static MutexOp sys_pthread_mutex_unlock = first_sys_pthread_mutex_unlock;
-static pthread_once_t init_sys_mutex_lock_once = PTHREAD_ONCE_INIT;
-
-// dlsym may call malloc to allocate space for dlerror and causes contention
-// profiler to deadlock at boostraping when the program is linked with
-// libunwind. The deadlock bt:
-// #0 0x00007effddc99b80 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
-// #1 0x00000000004b4df7 in butil::internal::SpinLockDelay(int volatile*, int, int) ()
-// #2 0x00000000004b4d57 in SpinLock::SlowLock() ()
-// #3 0x00000000004b4a63 in tcmalloc::ThreadCache::InitModule() ()
-// #4 0x00000000004aa2b5 in tcmalloc::ThreadCache::GetCache() ()
-// #5 0x000000000040c6c5 in (anonymous namespace)::do_malloc_no_errno(unsigned long) [clone.part.16] ()
-// #6 0x00000000006fc125 in tc_calloc ()
-// #7 0x00007effdd245690 in _dlerror_run (operate=operate@entry=0x7effdd245130 <dlsym_doit>, args=args@entry=0x7fff483dedf0) at dlerror.c:141
-// #8 0x00007effdd245198 in __dlsym (handle=<optimized out>, name=<optimized out>) at dlsym.c:70
-// #9 0x0000000000666517 in bthread::init_sys_mutex_lock () at bthread/mutex.cpp:358
-// #10 0x00007effddc97a90 in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:103
-// #11 0x000000000066649f in bthread::first_sys_pthread_mutex_lock (mutex=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:366
-// #12 0x00000000006678bc in pthread_mutex_lock_impl (mutex=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:489
-// #13 pthread_mutex_lock (__mutex=__mutex@entry=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:751
-// #14 0x00000000004c6ea1 in _ULx86_64_init () at x86_64/Gglobal.c:83
-// #15 0x00000000004c44fb in _ULx86_64_init_local (cursor=0x7fff483df340, uc=0x7fff483def90) at x86_64/Ginit_local.c:47
-// #16 0x00000000004b5012 in GetStackTrace(void**, int, int) ()
-// #17 0x00000000004b2095 in tcmalloc::PageHeap::GrowHeap(unsigned long) ()
-// #18 0x00000000004b23a3 in tcmalloc::PageHeap::New(unsigned long) ()
-// #19 0x00000000004ad457 in tcmalloc::CentralFreeList::Populate() ()
-// #20 0x00000000004ad628 in tcmalloc::CentralFreeList::FetchFromSpansSafe() ()
-// #21 0x00000000004ad6a3 in tcmalloc::CentralFreeList::RemoveRange(void**, void**, int) ()
-// #22 0x00000000004b3ed3 in tcmalloc::ThreadCache::FetchFromCentralCache(unsigned long, unsigned long) ()
-// #23 0x00000000006fbb9a in tc_malloc ()
-// Call _dl_sym which is a private function in glibc to workaround the malloc
-// causing deadlock temporarily. This fix is hardly portable.
-
-static void init_sys_mutex_lock() {
-#if defined(OS_LINUX)
- // TODO: may need dlvsym when GLIBC has multiple versions of a same symbol.
- // http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions
- if (_dl_sym) {
- sys_pthread_mutex_lock = (MutexOp)_dl_sym(RTLD_NEXT, "pthread_mutex_lock", (void*)init_sys_mutex_lock);
- sys_pthread_mutex_unlock = (MutexOp)_dl_sym(RTLD_NEXT, "pthread_mutex_unlock", (void*)init_sys_mutex_lock);
- } else {
- // _dl_sym may be undefined reference in some system, fallback to dlsym
- sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
- sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
- }
-#elif defined(OS_MACOSX)
- // TODO: look workaround for dlsym on mac
- sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
- sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
-#endif
-}
-
-// Make sure pthread functions are ready before main().
-const int ALLOW_UNUSED dummy = pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
-
-int first_sys_pthread_mutex_lock(pthread_mutex_t* mutex) {
- pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
- return sys_pthread_mutex_lock(mutex);
-}
-int first_sys_pthread_mutex_unlock(pthread_mutex_t* mutex) {
- pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
- return sys_pthread_mutex_unlock(mutex);
-}
+// #ifndef NO_PTHREAD_MUTEX_HOOK
+// // Replace pthread_mutex_lock and pthread_mutex_unlock:
+// // First call to sys_pthread_mutex_lock sets sys_pthread_mutex_lock to the
+// // real function so that next calls go to the real function directly. This
+// // technique avoids calling pthread_once each time.
+// typedef int (*MutexOp)(pthread_mutex_t*);
+// int first_sys_pthread_mutex_lock(pthread_mutex_t* mutex);
+// int first_sys_pthread_mutex_unlock(pthread_mutex_t* mutex);
+// static MutexOp sys_pthread_mutex_lock = first_sys_pthread_mutex_lock;
+// static MutexOp sys_pthread_mutex_unlock = first_sys_pthread_mutex_unlock;
+// static pthread_once_t init_sys_mutex_lock_once = PTHREAD_ONCE_INIT;
+
+// // dlsym may call malloc to allocate space for dlerror and causes contention
+// // profiler to deadlock at boostraping when the program is linked with
+// // libunwind. The deadlock bt:
+// // #0 0x00007effddc99b80 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
+// // #1 0x00000000004b4df7 in butil::internal::SpinLockDelay(int volatile*, int, int) ()
+// // #2 0x00000000004b4d57 in SpinLock::SlowLock() ()
+// // #3 0x00000000004b4a63 in tcmalloc::ThreadCache::InitModule() ()
+// // #4 0x00000000004aa2b5 in tcmalloc::ThreadCache::GetCache() ()
+// // #5 0x000000000040c6c5 in (anonymous namespace)::do_malloc_no_errno(unsigned long) [clone.part.16] ()
+// // #6 0x00000000006fc125 in tc_calloc ()
+// // #7 0x00007effdd245690 in _dlerror_run (operate=operate@entry=0x7effdd245130 <dlsym_doit>, args=args@entry=0x7fff483dedf0) at dlerror.c:141
+// // #8 0x00007effdd245198 in __dlsym (handle=<optimized out>, name=<optimized out>) at dlsym.c:70
+// // #9 0x0000000000666517 in bthread::init_sys_mutex_lock () at bthread/mutex.cpp:358
+// // #10 0x00007effddc97a90 in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:103
+// // #11 0x000000000066649f in bthread::first_sys_pthread_mutex_lock (mutex=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:366
+// // #12 0x00000000006678bc in pthread_mutex_lock_impl (mutex=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:489
+// // #13 pthread_mutex_lock (__mutex=__mutex@entry=0xbaf880 <_ULx86_64_lock>) at bthread/mutex.cpp:751
+// // #14 0x00000000004c6ea1 in _ULx86_64_init () at x86_64/Gglobal.c:83
+// // #15 0x00000000004c44fb in _ULx86_64_init_local (cursor=0x7fff483df340, uc=0x7fff483def90) at x86_64/Ginit_local.c:47
+// // #16 0x00000000004b5012 in GetStackTrace(void**, int, int) ()
+// // #17 0x00000000004b2095 in tcmalloc::PageHeap::GrowHeap(unsigned long) ()
+// // #18 0x00000000004b23a3 in tcmalloc::PageHeap::New(unsigned long) ()
+// // #19 0x00000000004ad457 in tcmalloc::CentralFreeList::Populate() ()
+// // #20 0x00000000004ad628 in tcmalloc::CentralFreeList::FetchFromSpansSafe() ()
+// // #21 0x00000000004ad6a3 in tcmalloc::CentralFreeList::RemoveRange(void**, void**, int) ()
+// // #22 0x00000000004b3ed3 in tcmalloc::ThreadCache::FetchFromCentralCache(unsigned long, unsigned long) ()
+// // #23 0x00000000006fbb9a in tc_malloc ()
+// // Call _dl_sym which is a private function in glibc to workaround the malloc
+// // causing deadlock temporarily. This fix is hardly portable.
+
+// static void init_sys_mutex_lock() {
+// #if defined(OS_LINUX)
+// // TODO: may need dlvsym when GLIBC has multiple versions of a same symbol.
+// // http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions
+// if (_dl_sym) {
+// sys_pthread_mutex_lock = (MutexOp)_dl_sym(RTLD_NEXT, "pthread_mutex_lock", (void*)init_sys_mutex_lock);
+// sys_pthread_mutex_unlock = (MutexOp)_dl_sym(RTLD_NEXT, "pthread_mutex_unlock", (void*)init_sys_mutex_lock);
+// } else {
+// // _dl_sym may be undefined reference in some system, fallback to dlsym
+// sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
+// sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
+// }
+// #elif defined(OS_MACOSX)
+// // TODO: look workaround for dlsym on mac
+// sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
+// sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
+// #endif
+// }
+
+// // Make sure pthread functions are ready before main().
+// const int ALLOW_UNUSED dummy = pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
+
+// int first_sys_pthread_mutex_lock(pthread_mutex_t* mutex) {
+// pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
+// return sys_pthread_mutex_lock(mutex);
+// }
+// int first_sys_pthread_mutex_unlock(pthread_mutex_t* mutex) {
+// pthread_once(&init_sys_mutex_lock_once, init_sys_mutex_lock);
+// return sys_pthread_mutex_unlock(mutex);
+// }
+// #endif
inline uint64_t hash_mutex_ptr(const pthread_mutex_t* m) {
return butil::fmix64((uint64_t)m);
@@ -524,99 +528,101 @@ void submit_contention(const bthread_contention_site_t& csite, int64_t now_ns) {
tls_inside_lock = false;
}
-BUTIL_FORCE_INLINE int pthread_mutex_lock_impl(pthread_mutex_t* mutex) {
- // Don't change behavior of lock when profiler is off.
- if (!g_cp ||
- // collecting code including backtrace() and submit() may call
- // pthread_mutex_lock and cause deadlock. Don't sample.
- tls_inside_lock) {
- return sys_pthread_mutex_lock(mutex);
- }
- // Don't slow down non-contended locks.
- int rc = pthread_mutex_trylock(mutex);
- if (rc != EBUSY) {
- return rc;
- }
- // Ask bvar::Collector if this (contended) locking should be sampled
- const size_t sampling_range = bvar::is_collectable(&g_cp_sl);
-
- bthread_contention_site_t* csite = NULL;
-#ifndef DONT_SPEEDUP_PTHREAD_CONTENTION_PROFILER_WITH_TLS
- TLSPthreadContentionSites& fast_alt = tls_csites;
- if (fast_alt.cp_version != g_cp_version) {
- fast_alt.cp_version = g_cp_version;
- fast_alt.count = 0;
- }
- if (fast_alt.count < TLS_MAX_COUNT) {
- MutexAndContentionSite& entry = fast_alt.list[fast_alt.count++];
- entry.mutex = mutex;
- csite = &entry.csite;
- if (!sampling_range) {
- make_contention_site_invalid(&entry.csite);
- return sys_pthread_mutex_lock(mutex);
- }
- }
-#endif
- if (!sampling_range) { // don't sample
- return sys_pthread_mutex_lock(mutex);
- }
- // Lock and monitor the waiting time.
- const int64_t start_ns = butil::cpuwide_time_ns();
- rc = sys_pthread_mutex_lock(mutex);
- if (!rc) { // Inside lock
- if (!csite) {
- csite = add_pthread_contention_site(mutex);
- if (csite == NULL) {
- return rc;
- }
- }
- csite->duration_ns = butil::cpuwide_time_ns() - start_ns;
- csite->sampling_range = sampling_range;
- } // else rare
- return rc;
-}
-
-BUTIL_FORCE_INLINE int pthread_mutex_unlock_impl(pthread_mutex_t* mutex) {
- // Don't change behavior of unlock when profiler is off.
- if (!g_cp || tls_inside_lock) {
- // This branch brings an issue that an entry created by
- // add_pthread_contention_site may not be cleared. Thus we add a
- // 16-bit rolling version in the entry to find out such entry.
- return sys_pthread_mutex_unlock(mutex);
- }
- int64_t unlock_start_ns = 0;
- bool miss_in_tls = true;
- bthread_contention_site_t saved_csite = {0,0};
-#ifndef DONT_SPEEDUP_PTHREAD_CONTENTION_PROFILER_WITH_TLS
- TLSPthreadContentionSites& fast_alt = tls_csites;
- for (int i = fast_alt.count - 1; i >= 0; --i) {
- if (fast_alt.list[i].mutex == mutex) {
- if (is_contention_site_valid(fast_alt.list[i].csite)) {
- saved_csite = fast_alt.list[i].csite;
- unlock_start_ns = butil::cpuwide_time_ns();
- }
- fast_alt.list[i] = fast_alt.list[--fast_alt.count];
- miss_in_tls = false;
- break;
- }
- }
-#endif
- // Check the map to see if the lock is sampled. Notice that we're still
- // inside critical section.
- if (miss_in_tls) {
- if (remove_pthread_contention_site(mutex, &saved_csite)) {
- unlock_start_ns = butil::cpuwide_time_ns();
- }
- }
- const int rc = sys_pthread_mutex_unlock(mutex);
- // [Outside lock]
- if (unlock_start_ns) {
- const int64_t unlock_end_ns = butil::cpuwide_time_ns();
- saved_csite.duration_ns += unlock_end_ns - unlock_start_ns;
- submit_contention(saved_csite, unlock_end_ns);
- }
- return rc;
-}
+// #ifndef NO_PTHREAD_MUTEX_HOOK
+// BUTIL_FORCE_INLINE int pthread_mutex_lock_impl(pthread_mutex_t* mutex) {
+// // Don't change behavior of lock when profiler is off.
+// if (!g_cp ||
+// // collecting code including backtrace() and submit() may call
+// // pthread_mutex_lock and cause deadlock. Don't sample.
+// tls_inside_lock) {
+// return sys_pthread_mutex_lock(mutex);
+// }
+// // Don't slow down non-contended locks.
+// int rc = pthread_mutex_trylock(mutex);
+// if (rc != EBUSY) {
+// return rc;
+// }
+// // Ask bvar::Collector if this (contended) locking should be sampled
+// const size_t sampling_range = bvar::is_collectable(&g_cp_sl);
+
+// bthread_contention_site_t* csite = NULL;
+// #ifndef DONT_SPEEDUP_PTHREAD_CONTENTION_PROFILER_WITH_TLS
+// TLSPthreadContentionSites& fast_alt = tls_csites;
+// if (fast_alt.cp_version != g_cp_version) {
+// fast_alt.cp_version = g_cp_version;
+// fast_alt.count = 0;
+// }
+// if (fast_alt.count < TLS_MAX_COUNT) {
+// MutexAndContentionSite& entry = fast_alt.list[fast_alt.count++];
+// entry.mutex = mutex;
+// csite = &entry.csite;
+// if (!sampling_range) {
+// make_contention_site_invalid(&entry.csite);
+// return sys_pthread_mutex_lock(mutex);
+// }
+// }
+// #endif
+// if (!sampling_range) { // don't sample
+// return sys_pthread_mutex_lock(mutex);
+// }
+// // Lock and monitor the waiting time.
+// const int64_t start_ns = butil::cpuwide_time_ns();
+// rc = sys_pthread_mutex_lock(mutex);
+// if (!rc) { // Inside lock
+// if (!csite) {
+// csite = add_pthread_contention_site(mutex);
+// if (csite == NULL) {
+// return rc;
+// }
+// }
+// csite->duration_ns = butil::cpuwide_time_ns() - start_ns;
+// csite->sampling_range = sampling_range;
+// } // else rare
+// return rc;
+// }
+
+// BUTIL_FORCE_INLINE int pthread_mutex_unlock_impl(pthread_mutex_t* mutex) {
+// // Don't change behavior of unlock when profiler is off.
+// if (!g_cp || tls_inside_lock) {
+// // This branch brings an issue that an entry created by
+// // add_pthread_contention_site may not be cleared. Thus we add a
+// // 16-bit rolling version in the entry to find out such entry.
+// return sys_pthread_mutex_unlock(mutex);
+// }
+// int64_t unlock_start_ns = 0;
+// bool miss_in_tls = true;
+// bthread_contention_site_t saved_csite = {0,0};
+// #ifndef DONT_SPEEDUP_PTHREAD_CONTENTION_PROFILER_WITH_TLS
+// TLSPthreadContentionSites& fast_alt = tls_csites;
+// for (int i = fast_alt.count - 1; i >= 0; --i) {
+// if (fast_alt.list[i].mutex == mutex) {
+// if (is_contention_site_valid(fast_alt.list[i].csite)) {
+// saved_csite = fast_alt.list[i].csite;
+// unlock_start_ns = butil::cpuwide_time_ns();
+// }
+// fast_alt.list[i] = fast_alt.list[--fast_alt.count];
+// miss_in_tls = false;
+// break;
+// }
+// }
+// #endif
+// // Check the map to see if the lock is sampled. Notice that we're still
+// // inside critical section.
+// if (miss_in_tls) {
+// if (remove_pthread_contention_site(mutex, &saved_csite)) {
+// unlock_start_ns = butil::cpuwide_time_ns();
+// }
+// }
+// const int rc = sys_pthread_mutex_unlock(mutex);
+// // [Outside lock]
+// if (unlock_start_ns) {
+// const int64_t unlock_end_ns = butil::cpuwide_time_ns();
+// saved_csite.duration_ns += unlock_end_ns - unlock_start_ns;
+// submit_contention(saved_csite, unlock_end_ns);
+// }
+// return rc;
+// }
+// #endif
// Implement bthread_mutex_t related functions
struct MutexInternal {
@@ -815,11 +821,13 @@ int bthread_mutex_unlock(bthread_mutex_t* m) {
return 0;
}
-int pthread_mutex_lock (pthread_mutex_t *__mutex) {
- return bthread::pthread_mutex_lock_impl(__mutex);
-}
-int pthread_mutex_unlock (pthread_mutex_t *__mutex) {
- return bthread::pthread_mutex_unlock_impl(__mutex);
-}
+// #ifndef NO_PTHREAD_MUTEX_HOOK
+// int pthread_mutex_lock (pthread_mutex_t *__mutex) {
+// return bthread::pthread_mutex_lock_impl(__mutex);
+// }
+// int pthread_mutex_unlock (pthread_mutex_t *__mutex) {
+// return bthread::pthread_mutex_unlock_impl(__mutex);
+// }
+// #endif
} // extern "C"