Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[xbt] Move backtrace support for exceptions in a mixin class
authorGabriel Corona <gabriel.corona@loria.fr>
Fri, 10 Jun 2016 11:54:52 +0000 (13:54 +0200)
committerGabriel Corona <gabriel.corona@loria.fr>
Mon, 13 Jun 2016 13:17:58 +0000 (15:17 +0200)
* mixin class to add backtraces to any exception;

* code to display exceptions with name, what(), backtraces and nested
  exceptions;

* demangle C++ names (class type names, function names).

16 files changed:
include/xbt/backtrace.hpp [new file with mode: 0644]
include/xbt/ex.h
include/xbt/exception.hpp [new file with mode: 0644]
include/xbt/log.hpp [new file with mode: 0644]
include/xbt/string.hpp
include/xbt/virtu.h
src/bindings/java/JavaContext.cpp
src/simix/smx_private.h
src/xbt/backtrace.cpp
src/xbt/backtrace_dummy.cpp
src/xbt/backtrace_linux.cpp
src/xbt/ex.cpp
src/xbt/ex_interface.h
src/xbt/exception.cpp [new file with mode: 0644]
src/xbt/log.c
tools/cmake/DefinePackages.cmake

diff --git a/include/xbt/backtrace.hpp b/include/xbt/backtrace.hpp
new file mode 100644 (file)
index 0000000..ca3f282
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2005-2019. The SimGrid Team.
+ * All rights reserved. */
+
+#ifndef SIMGRIX_XBT_BACKTRACE_HPP
+#define SIMGRIX_XBT_BACKTRACE_HPP
+
+#include <cstddef>
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include <xbt/base.h>
+#include <xbt/backtrace.h>
+
+namespace simgrid {
+namespace xbt {
+
+/** Try to demangle a C++ name
+ *
+ *  Return the origin string if this fails.
+ */
+XBT_PUBLIC() std::unique_ptr<char, void(*)(void*)> demangle(const char* name);
+
+/** Get the current backtrace */
+XBT_PUBLIC(std::vector<xbt_backtrace_location_t>) backtrace();
+
+/* Translate the backtrace in a human friendly form
+ *
+ *  Try ro resolve symbols and source code location.
+ */
+XBT_PUBLIC(std::vector<std::string>) resolveBacktrace(
+  xbt_backtrace_location_t const* loc, std::size_t count);
+
+}
+}
+
+#endif
index 6a4e505..d1e3fdf 100644 (file)
@@ -49,6 +49,7 @@
 #include <string>
 #include <vector>
 #include <stdexcept>
 #include <string>
 #include <vector>
 #include <stdexcept>
+#include <xbt/exception.hpp>
 #endif
 
 #include "xbt/base.h"
 #endif
 
 #include "xbt/base.h"
@@ -99,7 +100,9 @@ typedef enum {
 } xbt_errcat_t;
 
 #ifdef __cplusplus
 } xbt_errcat_t;
 
 #ifdef __cplusplus
-XBT_PUBLIC_CLASS xbt_ex : public std::runtime_error {
+XBT_PUBLIC_CLASS xbt_ex :
+  public std::runtime_error,
+  public simgrid::xbt::WithContextException {
 public:
   xbt_ex() : std::runtime_error("") {}
   xbt_ex(const char* message) : std::runtime_error(message) {}
 public:
   xbt_ex() : std::runtime_error("") {}
   xbt_ex(const char* message) : std::runtime_error(message) {}
@@ -107,13 +110,9 @@ public:
 
   xbt_errcat_t category;        /**< category like HTTP (what went wrong) */
   int value;                    /**< like errno (why did it went wrong) */
 
   xbt_errcat_t category;        /**< category like HTTP (what went wrong) */
   int value;                    /**< like errno (why did it went wrong) */
-  /* throw point */
-  std::string procname;         /**< Name of the process who thrown this */
-  int pid;                      /**< PID of the process who thrown this */
   const char *file;             /**< Thrown point */
   int line;                     /**< Thrown point */
   const char *func;             /**< Thrown point */
   const char *file;             /**< Thrown point */
   int line;                     /**< Thrown point */
   const char *func;             /**< Thrown point */
-  std::vector<void*>            bt; /**< Backtrace */
 };
 #endif
 
 };
 #endif
 
diff --git a/include/xbt/exception.hpp b/include/xbt/exception.hpp
new file mode 100644 (file)
index 0000000..c5d1358
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright (c) 2005-2016. The SimGrid Team.All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRID_XBT_EXCEPTION_HPP
+#define SIMGRID_XBT_EXCEPTION_HPP
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include <xbt/base.h>
+#include <xbt/backtrace.h>
+#include <xbt/backtrace.hpp>
+#include <xbt/log.h>
+#include <xbt/misc.h>  // xbt_procname
+#include <xbt/virtu.h> // xbt_getpid
+
+namespace simgrid {
+namespace xbt {
+
+typedef std::vector<xbt_backtrace_location_t> Backtrace;
+
+/** A polymorphic mixin class for adding context to an exception */
+XBT_PUBLIC_CLASS WithContextException {
+public:
+  WithContextException() :
+    backtrace_(simgrid::xbt::backtrace()),
+    procname_(xbt_procname()),
+    pid_(xbt_getpid())
+  {}
+  WithContextException(Backtrace bt) :
+    backtrace_(std::move(bt)),
+    procname_(xbt_procname()),
+    pid_(xbt_getpid())
+  {}
+  virtual ~WithContextException();
+  Backtrace const& backtrace() const
+  {
+    return backtrace_;
+  }
+  int pid() const { return pid_; }
+  std::string const& processName() const { return procname_; }
+private:
+  Backtrace backtrace_;
+  std::string procname_; /**< Name of the process who thrown this */
+  int pid_;              /**< PID of the process who thrown this */
+};
+
+/** Internal class used to mixin the two classes */
+template<class E>
+class WithContext : public E, public WithContextException
+{
+public:
+  WithContext(E exception)
+    : E(std::move(exception)) {}
+  WithContext(E exception, Backtrace backtrace)
+    : E(std::move(exception)), WithContextException(std::move(backtrace)) {}
+  WithContext(E exception, WithContextException context)
+    : E(std::move(exception)), WithContextException(std::move(context)) {}
+  ~WithContext() override {}
+};
+
+/** Throw a given exception a context
+ *
+ *  @param exception exception to throw
+ *  @param backtrace backtrace to attach
+ */
+template<class E>
+[[noreturn]] inline
+typename std::enable_if< !std::is_base_of<WithContextException,E>::value >::type
+throwWithContext(
+  E exception,
+  // Thanks to the default argument, we are taking the backtrace in the caller:
+  Backtrace backtrace = simgrid::xbt::backtrace())
+{
+ throw WithContext<E>(std::move(exception), std::move(backtrace));
+}
+
+}
+}
+
+#endif
diff --git a/include/xbt/log.hpp b/include/xbt/log.hpp
new file mode 100644 (file)
index 0000000..781559d
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (c) 2016. The SimGrid Team. All rights reserved.*/
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/log.h>
+#include <xbt/exception.hpp>
+
+namespace simgrid {
+namespace xbt {
+
+/** Display informations about an exception
+ *
+ *  We display: the exception type, name, attached backtarces (if any) and
+ *  the nested exception (if any).
+ */
+XBT_PUBLIC(void) logException(
+  e_xbt_log_priority_t priority,
+  const char* context, std::exception const& exception);
+
+}
+}
index 2fcd61a..9ffff03 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <string>
 #include <cstdarg>
 
 #include <string>
 #include <cstdarg>
+#include <stdlib.h>
 
 #if HAVE_MC
 
 
 #if HAVE_MC
 
index 2f140fe..07b895d 100644 (file)
@@ -10,7 +10,7 @@
 #define __XBT_VIRTU_H__
 
 #include "xbt/misc.h"
 #define __XBT_VIRTU_H__
 
 #include "xbt/misc.h"
-#include "xbt/sysdep.h"
+#include "xbt/base.h"
 #include "xbt/function_types.h"
 #include "xbt/dynar.h"
 
 #include "xbt/function_types.h"
 #include "xbt/dynar.h"
 
index c6a3d48..9d0218d 100644 (file)
@@ -84,16 +84,12 @@ JavaContext::JavaContext(std::function<void()> code,
         "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
         thread_amount, ex.what());
       xbt_ex new_exception(str);
         "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
         thread_amount, ex.what());
       xbt_ex new_exception(str);
-      free(str);
       new_exception.category = ex.category;
       new_exception.value = ex.value;
       new_exception.category = ex.category;
       new_exception.value = ex.value;
-      new_exception.procname = ex.procname;
-      new_exception.file = ex.file;
-      new_exception.line = ex.line;
-      new_exception.func = ex.func;
-      new_exception.pid = ex.pid;
-      new_exception.bt = ex.bt;
-      throw new_exception;
+      new_exception.file = __FILE__;
+      new_exception.line = __LINE__;
+      new_exception.func = __func__;
+      std::throw_with_nested(std::move(new_exception));
     }
   } else {
     this->thread = nullptr;
     }
   } else {
     this->thread = nullptr;
index 333ea07..feb9990 100644 (file)
@@ -90,8 +90,6 @@ XBT_PUBLIC(void) SIMIX_clean(void);
   xbt_ex e(msg); \
   e.category = cat; \
   e.value = val; \
   xbt_ex e(msg); \
   e.category = cat; \
   e.value = val; \
-  e.procname = xbt_procname(); \
-  e.pid = xbt_getpid(); \
   e.file = __FILE__; \
   e.line = __LINE__; \
   e.func = __func__; \
   e.file = __FILE__; \
   e.line = __LINE__; \
   e.func = __func__; \
index f897e12..669856a 100644 (file)
@@ -1,9 +1,22 @@
 /* Copyright (c) 2005-2016. The SimGrid Team. All rights reserved.          */
 
 /* Copyright (c) 2005-2016. The SimGrid Team. All rights reserved.          */
 
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
 #include <cstddef>
 #include <cstddef>
+#include <cstdlib>
+
+#include <vector>
+
+// Try to detect and use the C++ intanium ABI for name demangling:
+#ifdef __GXX_ABI_VERSION
+#include <cxxabi.h>
+#endif
 
 
-#include <xbt/log.h>
 #include <xbt/backtrace.h>
 #include <xbt/backtrace.h>
+#include <xbt/backtrace.hpp>
+#include <xbt/log.h>
+#include <xbt/sysdep.h>
 
 #include "src/internal_config.h"
 
 
 #include "src/internal_config.h"
 
@@ -22,6 +35,37 @@ void xbt_backtrace_display_current(void)
   xbt_backtrace_display(bt, used);
 }
 
   xbt_backtrace_display(bt, used);
 }
 
+namespace simgrid {
+namespace xbt {
+
+std::unique_ptr<char, void(*)(void*)> demangle(const char* name)
+{
+#ifdef __GXX_ABI_VERSION
+  int status;
+  auto res = std::unique_ptr<char, void(*)(void*)>(
+    abi::__cxa_demangle(name, NULL, NULL, &status),
+    std::free
+  );
+  if (res != nullptr)
+    return res;
+  // We did not manage to resolve this. Probably because this is not a mangled
+  // symbol:
+#endif
+  // Return the symbol:
+  return std::unique_ptr<char, void(*)(void*)>(xbt_strdup(name), std::free);
+}
+
+std::vector<xbt_backtrace_location_t> backtrace()
+{
+  const std::size_t size = 10;
+  xbt_backtrace_location_t loc[size];
+  size_t used = xbt_backtrace_current(loc, size);
+  return std::vector<xbt_backtrace_location_t>(loc, loc + used);
+}
+
+}
+}
+
 #if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE)
 # include "src/xbt/backtrace_linux.cpp"
 #else
 #if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE)
 # include "src/xbt/backtrace_linux.cpp"
 #else
index 4125fb7..115b7db 100644 (file)
@@ -10,6 +10,8 @@
 #include "src/xbt_modinter.h"
 #include "src/xbt/ex_interface.h"
 
 #include "src/xbt_modinter.h"
 #include "src/xbt/ex_interface.h"
 
+#include <xbt/backtrace.hpp>
+
 /* Module creation/destruction */
 void xbt_backtrace_preinit(void)
 {
 /* Module creation/destruction */
 void xbt_backtrace_preinit(void)
 {
@@ -33,7 +35,7 @@ namespace simgrid {
 namespace xbt {
 
 std::vector<std::string> resolveBacktrace(
 namespace xbt {
 
 std::vector<std::string> resolveBacktrace(
-  xbt_backtrace_location_t* loc, std::size_t count)
+  xbt_backtrace_location_t const* loc, std::size_t count)
 {
   return std::vector<std::string>();
 }
 {
   return std::vector<std::string>();
 }
index 19b15ab..80cd509 100644 (file)
@@ -1,7 +1,7 @@
 /* backtrace_linux - backtrace displaying on linux platform                 */
 /* This file is included by ex.cpp on need (have execinfo.h, popen & addrline)*/
 
 /* backtrace_linux - backtrace displaying on linux platform                 */
 /* This file is included by ex.cpp on need (have execinfo.h, popen & addrline)*/
 
-/* Copyright (c) 2008-2015. The SimGrid Team.
+/* Copyright (c) 2008-2016. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -19,6 +19,7 @@
 
 /* This file is to be included in ex.cpp, so the following headers are not mandatory, but it's to make sure that eclipse see them too */
 #include <xbt/string.hpp>
 
 /* This file is to be included in ex.cpp, so the following headers are not mandatory, but it's to make sure that eclipse see them too */
 #include <xbt/string.hpp>
+#include <xbt/backtrace.hpp>
 #include "xbt/ex.h"
 #include "src/xbt/ex_interface.h"
 #include "xbt/log.h"
 #include "xbt/ex.h"
 #include "src/xbt/ex_interface.h"
 #include "xbt/log.h"
@@ -114,6 +115,9 @@ static std::string get_binary_path()
 {
   struct stat stat_buf;
 
 {
   struct stat stat_buf;
 
+  if (xbt_binary_name == nullptr)
+    return "";
+
   // We found it, we are happy:
   if (stat(xbt_binary_name, &stat_buf) == 0)
     return xbt_binary_name;
   // We found it, we are happy:
   if (stat(xbt_binary_name, &stat_buf) == 0)
     return xbt_binary_name;
@@ -144,23 +148,28 @@ static std::string get_binary_path()
 //FIXME: This code could be greatly improved/simplifyied with
 //   http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html
 std::vector<std::string> resolveBacktrace(
 //FIXME: This code could be greatly improved/simplifyied with
 //   http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html
 std::vector<std::string> resolveBacktrace(
-  xbt_backtrace_location_t* loc, std::size_t count)
+  xbt_backtrace_location_t const* loc, std::size_t count)
 {
   std::vector<std::string> result;
 
 {
   std::vector<std::string> result;
 
-  /* no binary name, nothing to do */
-  if (xbt_binary_name == NULL)
-    return result;
-
   if (count == 0)
     return result;
 
   if (count == 0)
     return result;
 
+  if (xbt_binary_name == nullptr)
+    XBT_WARN("XBT not initialized, the backtrace will not be resolved.");
+
   // Drop the first one:
   loc++; count--;
 
   char** backtrace_syms = backtrace_symbols(loc, count);
   std::string binary_name = get_binary_path();
 
   // Drop the first one:
   loc++; count--;
 
   char** backtrace_syms = backtrace_symbols(loc, count);
   std::string binary_name = get_binary_path();
 
+  if (binary_name.empty()) {
+    for (std::size_t i = 0; i < count; i++)
+      result.push_back(simgrid::xbt::string_printf("%p", loc[i]));
+    return std::move(result);
+  }
+
   // Create the system command for add2line:
   std::ostringstream stream;
   stream << ADDR2LINE << " -f -e " << binary_name << ' ';
   // Create the system command for add2line:
   std::ostringstream stream;
   stream << ADDR2LINE << " -f -e " << binary_name << ' ';
@@ -209,9 +218,10 @@ std::vector<std::string> resolveBacktrace(
     }
 
     if (strcmp("??", line_func) != 0) {
     }
 
     if (strcmp("??", line_func) != 0) {
-      XBT_DEBUG("Found static symbol %s() at %s", line_func, line_pos);
+      auto name = simgrid::xbt::demangle(line_func);
+      XBT_DEBUG("Found static symbol %s at %s", name.get(), line_pos);
       result.push_back(simgrid::xbt::string_printf(
       result.push_back(simgrid::xbt::string_printf(
-        "%s() at %s", line_func, line_pos
+        "%s at %s, %p", name.get(), line_pos, loc[i]
       ));
     } else {
       /* Damn. The symbol is in a dynamic library. Let's get wild */
       ));
     } else {
       /* Damn. The symbol is in a dynamic library. Let's get wild */
@@ -312,9 +322,10 @@ std::vector<std::string> resolveBacktrace(
 
       /* check whether the trick worked */
       if (strcmp("??", line_func)) {
 
       /* check whether the trick worked */
       if (strcmp("??", line_func)) {
-        XBT_DEBUG("Found dynamic symbol %s() at %s", line_func, line_pos);
+        auto name = simgrid::xbt::demangle(line_func);
+        XBT_DEBUG("Found dynamic symbol %s at %s", name.get(), line_pos);
         result.push_back(simgrid::xbt::string_printf(
         result.push_back(simgrid::xbt::string_printf(
-          "%s() at %s", line_func, line_pos));
+          "%s at %s, %p", name.get(), line_pos, loc[i]));
       } else {
         /* damn, nothing to do here. Let's print the raw address */
         XBT_DEBUG("Dynamic symbol not found. Raw address = %s", backtrace_syms[i]);
       } else {
         /* damn, nothing to do here. Let's print the raw address */
         XBT_DEBUG("Dynamic symbol not found. Raw address = %s", backtrace_syms[i]);
index 2fd2e3b..2ba0698 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <xbt/backtrace.hpp>
 #include "src/internal_config.h"           /* execinfo when available */
 #include "xbt/ex.h"
 #include "src/internal_config.h"           /* execinfo when available */
 #include "xbt/ex.h"
+#include "xbt/log.h"
+#include "xbt/log.hpp"
 #include "xbt/backtrace.h"
 #include "xbt/backtrace.h"
+#include "xbt/backtrace.hpp"
 #include "xbt/str.h"
 #include "xbt/synchro_core.h"
 #include "src/xbt_modinter.h"       /* backtrace initialization headers */
 #include "xbt/str.h"
 #include "xbt/synchro_core.h"
 #include "src/xbt_modinter.h"       /* backtrace initialization headers */
@@ -57,6 +61,7 @@
 
 #include "simgrid/simix.h" /* SIMIX_process_self_get_name() */
 
 
 #include "simgrid/simix.h" /* SIMIX_process_self_get_name() */
 
+
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mechanism");
 
 xbt_ex::~xbt_ex() {}
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mechanism");
 
 xbt_ex::~xbt_ex() {}
@@ -93,72 +98,13 @@ void xbt_throw(
   e.file = file;
   e.line = line;
   e.func = func;
   e.file = file;
   e.line = line;
   e.func = func;
-  e.procname = xbt_procname();
-  e.pid = xbt_getpid();
   throw e;
 }
 
 /** @brief shows an exception content and the associated stack if available */
 void xbt_ex_display(xbt_ex_t * e)
 {
   throw e;
 }
 
 /** @brief shows an exception content and the associated stack if available */
 void xbt_ex_display(xbt_ex_t * e)
 {
-  char *thrower = NULL;
-  if (e->pid != xbt_getpid())
-    thrower = bprintf(" on process %d",e->pid);
-
-  std::fprintf(stderr, "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n"
-          "** %s\n"
-          "** Thrown by %s()%s\n",
-          xbt_binary_name, xbt_getpid(), xbt_ex_catname(e->category), e->value, e->what(),
-          e->procname.c_str(), thrower ? thrower : " in this process");
-  XBT_CRITICAL("%s", e->what());
-  xbt_free(thrower);
-
-  if (xbt_initialized==0 || smx_cleaned) {
-    fprintf(stderr, "Ouch. SimGrid is not initialized yet, or already closing. No backtrace available.\n");
-    return; /* Not started yet or already closing. Trying to generate a backtrace would probably fail */
-  }
-
-  std::vector<std::string> backtrace = simgrid::xbt::resolveBacktrace(
-    e->bt.data(), e->bt.size());
-
-#ifdef HAVE_BACKTRACE
-  if (!backtrace.empty()) {
-    /* We have everything to build neat backtraces */
-    int cutpath = 0;
-    try { // We don't want to have an exception while checking how to deal with the one we already have, do we?
-      cutpath = xbt_cfg_get_boolean("exception/cutpath");
-    }
-    catch(xbt_ex& e) {
-      // Nothing to do
-    }
-
-    std::fprintf(stderr, "\n");
-    for (std::string const& s : backtrace) {
-
-      // TODO, move this logic into solveBacktrace
-      if (cutpath) {
-        // TODO, simplify this
-        char* p = xbt_strdup(s.c_str());
-        xbt_str_rtrim(p, ":0123456789");
-        char* filename = strrchr(p, '/')+1;
-        char* end_of_message  = strrchr(p, ' ');
-        int length = strlen(p)-strlen(end_of_message);
-        char* dest = (char*) std::malloc(length);
-        std::memcpy(dest, &p[0], length);
-        dest[length] = 0;
-        std::fprintf(stderr, "%s %s\n", dest, filename);
-        std::free(dest);
-        std::free(p);
-      }
-      else {
-        std::fprintf(stderr, "%s\n", s.c_str());
-      }
-    }
-  } else
-#endif
-    std::fprintf(stderr, "\n"
-        "**   In %s() at %s:%d\n"
-        "**   (no backtrace available)\n", e->func, e->file, e->line);
+  simgrid::xbt::logException(xbt_log_priority_critical, "UNCAUGHT EXCEPTION", *e);
 }
 
 /** \brief returns a short name for the given exception category */
 }
 
 /** \brief returns a short name for the given exception category */
index cbff4ea..3c7599e 100644 (file)
 namespace simgrid {
 namespace xbt {
 
 namespace simgrid {
 namespace xbt {
 
-/* Change raw libc symbols to file names and line numbers */
-XBT_PUBLIC(std::vector<std::string>) resolveBacktrace(
-  xbt_backtrace_location_t* loc, std::size_t count);
-
 }
 }
 
 }
 }
 
diff --git a/src/xbt/exception.cpp b/src/xbt/exception.cpp
new file mode 100644 (file)
index 0000000..6e9cf0c
--- /dev/null
@@ -0,0 +1,72 @@
+/* Copyright (c) 2005-2016. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <exception>
+#include <typeinfo>
+#include <memory>
+
+#include <xbt/backtrace.hpp>
+#include <xbt/exception.hpp>
+#include <xbt/log.h>
+#include <xbt/log.hpp>
+
+extern "C" {
+XBT_LOG_EXTERNAL_CATEGORY(xbt);
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_exception, xbt, "Exceptions");
+}
+
+namespace simgrid {
+namespace xbt {
+
+WithContextException::~WithContextException() {}
+
+void logException(
+  e_xbt_log_priority_t prio,
+  const char* context, std::exception const& exception)
+{
+  try {
+    auto name = simgrid::xbt::demangle(typeid(exception).name());
+
+    auto with_context =
+      dynamic_cast<const simgrid::xbt::WithContextException*>(&exception);
+    if (with_context != nullptr)
+      XBT_LOG(prio, "%s %s by %s/%d: %s",
+        context, name.get(),
+        with_context->processName().c_str(), with_context->pid(),
+        exception.what());
+    else
+      XBT_LOG(prio, "%s %s: %s", context, name.get(), exception.what());
+
+    // Do we have a backtrace?
+    if (with_context != nullptr) {
+      auto backtrace = simgrid::xbt::resolveBacktrace(
+        with_context->backtrace().data(), with_context->backtrace().size());
+      for (std::string const& s : backtrace)
+        XBT_LOG(prio, "  -> %s", s.c_str());
+    }
+
+    // Do we have a nested exception?
+    auto with_nested = dynamic_cast<const std::nested_exception*>(&exception);
+    if (with_nested == nullptr ||  with_nested->nested_ptr() == nullptr)
+      return;
+    try {
+      with_nested->rethrow_nested();
+    }
+    catch (std::exception& nested_exception) {
+      logException(prio, "Caused by", nested_exception);
+    }
+    // We could catch nested_exception or WithContextException but we don't bother:
+    catch (...) {
+      XBT_LOG(prio, "Caused by an unknown exception");
+    }
+  }
+  catch (...) {
+    // Don't log exceptions we got when trying to log exception
+  }
+}
+
+}
+}
index 23482c3..7c57168 100644 (file)
@@ -107,6 +107,7 @@ static void xbt_log_connect_categories(void)
   XBT_LOG_CONNECT(xbt_dyn);
   XBT_LOG_CONNECT(xbt_ex);
   XBT_LOG_CONNECT(xbt_backtrace);
   XBT_LOG_CONNECT(xbt_dyn);
   XBT_LOG_CONNECT(xbt_ex);
   XBT_LOG_CONNECT(xbt_backtrace);
+  XBT_LOG_CONNECT(xbt_exception);
   XBT_LOG_CONNECT(xbt_fifo);
   XBT_LOG_CONNECT(xbt_graph);
   XBT_LOG_CONNECT(xbt_heap);
   XBT_LOG_CONNECT(xbt_fifo);
   XBT_LOG_CONNECT(xbt_graph);
   XBT_LOG_CONNECT(xbt_heap);
index 87ef125..eb8ef77 100644 (file)
@@ -252,6 +252,7 @@ set(XBT_SRC
   src/xbt/dict_elm.c
   src/xbt/dynar.cpp
   src/xbt/ex.cpp
   src/xbt/dict_elm.c
   src/xbt/dynar.cpp
   src/xbt/ex.cpp
+  src/xbt/exception.cpp
   src/xbt/fifo.c
   src/xbt/graph.c
   src/xbt/heap.c
   src/xbt/fifo.c
   src/xbt/graph.c
   src/xbt/heap.c
@@ -667,7 +668,9 @@ set(headers_to_install
   include/xbt/dynar.h
   include/xbt/dynar.hpp
   include/xbt/ex.h
   include/xbt/dynar.h
   include/xbt/dynar.hpp
   include/xbt/ex.h
+  include/xbt/exception.hpp
   include/xbt/backtrace.h
   include/xbt/backtrace.h
+  include/xbt/backtrace.hpp
   include/xbt/fifo.h
   include/xbt/file.h
   include/xbt/function_types.h
   include/xbt/fifo.h
   include/xbt/file.h
   include/xbt/function_types.h
@@ -678,6 +681,7 @@ set(headers_to_install
   include/xbt/lib.h
   include/xbt/Extendable.hpp
   include/xbt/log.h
   include/xbt/lib.h
   include/xbt/Extendable.hpp
   include/xbt/log.h
+  include/xbt/log.hpp
   include/xbt/mallocator.h
   include/xbt/matrix.h
   include/xbt/memory.hpp
   include/xbt/mallocator.h
   include/xbt/matrix.h
   include/xbt/memory.hpp