]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
include/assert: Smarten up ceph_assert
authorAdam C. Emerson <aemerson@redhat.com>
Thu, 23 Aug 2018 19:39:11 +0000 (15:39 -0400)
committerAdam C. Emerson <aemerson@redhat.com>
Mon, 27 Aug 2018 14:27:22 +0000 (10:27 -0400)
Change ceph_assert_msg to not require a CephContext. Add
ceph_assert_msgf that accepts a format string.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/common/assert.cc
src/include/assert.h
src/kv/RocksDBStore.cc

index 623b3150b492640b599842b726fba3bd2f3b10d5..239bd6db0afc14633834dc04132fac6856af30b8 100644 (file)
@@ -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);
index 93a45e85dbb3181ab425441ca531583187d3c1ce..5fb985503ad9c8675060db5b1e233ca62dc63aa6 100644 (file)
@@ -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 = \
index fd02b8315c9213e9b269c4985babb614f68f5276..f484fb20c5f1f2d4c62c999e7120c06a769784ee 100644 (file)
@@ -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);