diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/assert.cc | 125 | ||||
-rw-r--r-- | src/include/assert.h | 21 | ||||
-rw-r--r-- | src/kv/RocksDBStore.cc | 8 |
3 files changed, 117 insertions, 37 deletions
diff --git a/src/common/assert.cc b/src/common/assert.cc index 623b3150b49..239bd6db0af 100644 --- a/src/common/assert.cc +++ b/src/common/assert.cc @@ -79,6 +79,35 @@ namespace ceph { __ceph_assert_fail(ctx.assertion, ctx.file, ctx.line, ctx.function); } + class BufAppender { + public: + BufAppender(char* buf, int size) : bufptr(buf), remaining(size) {} + + void printf(const char * format, ...) { + va_list args; + va_start(args, format); + this->vprintf(format, args); + va_end(args); + } + + void vprintf(const char * format, va_list args) { + int n = vsnprintf(bufptr, remaining, format, args); + if (n >= 0) { + if (n < remaining) { + remaining -= n; + bufptr += n; + } else { + remaining = 0; + } + } + } + + private: + char* bufptr; + int remaining; + }; + + [[gnu::cold]] void __ceph_assertf_fail(const char *assertion, const char *file, int line, const char *func, const char* msg, @@ -95,43 +124,85 @@ namespace ceph { ceph_pthread_getname(pthread_self(), g_assert_thread_name, sizeof(g_assert_thread_name)); - class BufAppender { - public: - BufAppender(char* buf, int size) : bufptr(buf), remaining(size) { - } + char buf[8096]; + BufAppender ba(buf, sizeof(buf)); + BackTrace *bt = new BackTrace(1); + ba.printf("%s: In function '%s' thread %llx time %s\n" + "%s: %d: FAILED ceph_assert(%s)\n", + file, func, (unsigned long long)pthread_self(), tss.str().c_str(), + file, line, assertion); + ba.printf("Assertion details: "); + va_list args; + va_start(args, msg); + ba.vprintf(msg, args); + va_end(args); + ba.printf("\n"); + dout_emergency(buf); - void printf(const char * format, ...) { - va_list args; - va_start(args, format); - this->vprintf(format, args); - va_end(args); + // TODO: get rid of this memory allocation. + ostringstream oss; + oss << *bt; + dout_emergency(oss.str()); + + if (g_assert_context) { + lderr(g_assert_context) << buf << std::endl; + *_dout << oss.str() << dendl; + + // dump recent only if the abort signal handler won't do it for us + if (!g_assert_context->_conf->fatal_signal_handlers) { + g_assert_context->_log->dump_recent(); } + } - void vprintf(const char * format, va_list args) { - int n = vsnprintf(bufptr, remaining, format, args); - if (n >= 0) { - if (n < remaining) { - remaining -= n; - bufptr += n; - } else { - remaining = 0; - } - } + abort(); + } + + [[gnu::cold]] void __ceph_abort(const char *file, int line, + const char *func, const string& msg) + { + ostringstream tss; + tss << ceph_clock_now(); + + BackTrace *bt = new BackTrace(1); + ba.printf("%s: In function '%s' thread %llx time %s\n" + "%s: %d: abort()\n", + file, func, (unsigned long long)pthread_self(), tss.str().c_str(), + file, line); + dout_emergency(msg); + + // TODO: get rid of this memory allocation. + ostringstream oss; + oss << *bt; + dout_emergency(oss.str()); + + if (g_assert_context) { + lderr(g_assert_context) << buf << std::endl; + *_dout << oss.str() << dendl; + + // dump recent only if the abort signal handler won't do it for us + if (!g_assert_context->_conf->fatal_signal_handlers) { + g_assert_context->_log->dump_recent(); } + } - private: - char* bufptr; - int remaining; - }; + abort(); + } + + [[gnu::cold]] void __ceph_abortf(const char *file, int line, + const char *func, const char* msg, + ...) + { + ostringstream tss; + tss << ceph_clock_now(); char buf[8096]; BufAppender ba(buf, sizeof(buf)); BackTrace *bt = new BackTrace(1); ba.printf("%s: In function '%s' thread %llx time %s\n" - "%s: %d: FAILED ceph_assert(%s)\n", - file, func, (unsigned long long)pthread_self(), tss.str().c_str(), - file, line, assertion); - ba.printf("Assertion details: "); + "%s: %d: abort()\n", + file, func, (unsigned long long)pthread_self(), tss.str().c_str(), + file, line); + ba.printf("Abort details: "); va_list args; va_start(args, msg); ba.vprintf(msg, args); diff --git a/src/include/assert.h b/src/include/assert.h index 93a45e85dbb..5fb985503ad 100644 --- a/src/include/assert.h +++ b/src/include/assert.h @@ -1,7 +1,8 @@ #ifndef CEPH_ASSERT_H #define CEPH_ASSERT_H -#include <stdlib.h> +#include <cstdlib> +#include <string> #if defined(__linux__) #include <features.h> @@ -78,6 +79,12 @@ extern void __ceph_assertf_fail(const char *assertion, const char *file, int lin __attribute__ ((__noreturn__)); extern void __ceph_assert_warn(const char *assertion, const char *file, int line, const char *function); +[[noreturn]] void __ceph_abort(const char *file, int line, const char *func, + const std::string& msg); + +[[noreturn]] void __ceph_abortf(const char *file, int line, const char *func, + const char* msg, ...); + #define _CEPH_ASSERT_VOID_CAST static_cast<void> #define assert_warn(expr) \ @@ -96,12 +103,14 @@ using namespace ceph; * Currently, it's the same as assert(0), but we may one day make assert a * debug-only thing, like it is in many projects. */ -#define ceph_abort() abort() +#define ceph_abort(msg, ...) \ + __ceph_abort( __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION, "abort() called") + +#define ceph_abort_msg(msg) \ + __ceph_abort( __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION, msg) -#define ceph_abort_msg(cct, msg) { \ - lgeneric_derr(cct) << "abort: " << msg << dendl; \ - abort(); \ - } +#define ceph_abort_msgf(...) \ + __ceph_abortf( __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION, __VA_ARGS__) #define ceph_assert(expr) \ do { static const ceph::assert_data assert_data_ctx = \ diff --git a/src/kv/RocksDBStore.cc b/src/kv/RocksDBStore.cc index fd02b8315c9..f484fb20c5f 100644 --- a/src/kv/RocksDBStore.cc +++ b/src/kv/RocksDBStore.cc @@ -1056,7 +1056,7 @@ int RocksDBStore::get( if (status.ok()) { (*out)[key].append(value); } else if (status.IsIOError()) { - ceph_abort_msg(cct, status.ToString()); + ceph_abort_msg(status.getState()); } } } else { @@ -1070,7 +1070,7 @@ int RocksDBStore::get( if (status.ok()) { (*out)[key].append(value); } else if (status.IsIOError()) { - ceph_abort_msg(cct, status.ToString()); + ceph_abort_msg(status.getState()); } } } @@ -1108,7 +1108,7 @@ int RocksDBStore::get( } else if (s.IsNotFound()) { r = -ENOENT; } else { - ceph_abort_msg(cct, s.ToString()); + ceph_abort_msg(s.getState()); } utime_t lat = ceph_clock_now() - start; logger->inc(l_rocksdb_gets); @@ -1146,7 +1146,7 @@ int RocksDBStore::get( } else if (s.IsNotFound()) { r = -ENOENT; } else { - ceph_abort_msg(cct, s.ToString()); + ceph_abort_msg(s.getState()); } utime_t lat = ceph_clock_now() - start; logger->inc(l_rocksdb_gets); |