From 16cd9173dd36dd73ffbb2fbca43ed1e215db12f1 Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Mon, 14 Feb 2011 07:20:57 -0800 Subject: [PATCH] assert: allow assertions inside calls to dout() We should handle the situation where we assert() while already holding the dout() lock. At the same time, we want to get the dout lock if we can, because it makes the logs look nicer. pthread_mutex_trylock solves the dilemma. Signed-off-by: Colin McCabe --- src/common/assert.cc | 53 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/common/assert.cc b/src/common/assert.cc index 60bdef80cf61d..c4a5c744eb0a2 100644 --- a/src/common/assert.cc +++ b/src/common/assert.cc @@ -12,19 +12,51 @@ * */ +#include #include +#include #include +#include #include "BackTrace.h" #include "common/debug.h" #include "config.h" #include "include/assert.h" +static bool dout_trylock(void) +{ + time_t cur; + time_t end_time = time(NULL); + end_time += 10; + + do { + int ret = pthread_mutex_trylock(&_dout_lock); + if (ret == 0) { + // We got the mutex. + return true; + } + else if ((ret == EDEADLK) || (ret == EAGAIN)) { + // This thread already owns the mutex. + // The assertion happened inside a call to dout()? + return false; + } + else if (ret == EINVAL) { + // We can never get the mutex. + return false; + } + // Otherwise, keep trying. + usleep(1000); + cur = time(NULL); + } while (cur < end_time); + + // If 10 seconds go by and we can't get the mutex, just bail. + return false; +} + namespace ceph { void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *func) { - // TODO: replace this with a trylock - DoutLocker _dout_locker; + int got_lock = dout_trylock(); char buf[8096]; BackTrace *bt = new BackTrace(1); @@ -44,19 +76,32 @@ namespace ceph { "is needed to interpret this.\n"); dout_emergency(oss.str()); + if (got_lock) { + int ret = pthread_mutex_unlock(&_dout_lock); + if (ret) { + ; // ignored + } + } + throw FailedAssertion(bt); } void __ceph_assert_warn(const char *assertion, const char *file, int line, const char *func) { - // TODO: replace this with a trylock - DoutLocker _dout_locker; + int got_lock = dout_trylock(); char buf[8096]; snprintf(buf, sizeof(buf), "WARNING: assert(%s) at: %s: %d: %s()\n", assertion, file, line, func); dout_emergency(buf); + + if (got_lock) { + int ret = pthread_mutex_unlock(&_dout_lock); + if (ret) { + ; // ignored + } + } } } -- 2.39.5