Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Replace sprintf by snprintf.
[simgrid.git] / src / xbt / ex.c
index e53837c..0a4e65e 100644 (file)
@@ -1,6 +1,8 @@
 /* ex - Exception Handling                                                  */
 
-/*  Copyright (c) 2005-2013. The SimGrid Team.                              */
+/* Copyright (c) 2005-2015. The SimGrid Team.
+ * All rights reserved.                                                     */
+
 /*  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>       */
 /*  Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/>         */
 /*  Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/>           */
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "portable.h"           /* execinfo when available */
+#include "src/internal_config.h"           /* execinfo when available */
 #include "xbt/ex.h"
 #include "xbt/str.h"
 #include "xbt/synchro_core.h"
-#include "xbt_modinter.h"       /* backtrace initialization headers */
-
-#include "xbt/ex_interface.h"
+#include "src/xbt_modinter.h"       /* backtrace initialization headers */
 
-#undef HAVE_BACKTRACE
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
-# define HAVE_BACKTRACE 1       /* Hello linux box */
-#endif
-
-#if defined(_XBT_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
-# define HAVE_BACKTRACE 1       /* Hello x86 windows box */
-#endif
+#include "src/xbt/ex_interface.h"
+#include "simgrid/sg_config.h"  /* Configuration mechanism of SimGrid */
 
+#include "simgrid/simix.h" /* SIMIX_process_self_get_name() */
 
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mecanism");
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mechanism");
 
 XBT_EXPORT_NO_IMPORT(const xbt_running_ctx_t) __xbt_ex_ctx_initializer = XBT_RUNNING_CTX_INITIALIZER;
 
@@ -94,11 +89,8 @@ void xbt_backtrace_display(xbt_ex_t * e)
   if (e->used == 0) {
     fprintf(stderr, "(backtrace not set)\n");
   } else {
-    int i;
-
-    fprintf(stderr, "Backtrace (displayed in thread %p):\n",
-            (void *) xbt_thread_self());
-    for (i = 1; i < e->used; i++)       /* no need to display "xbt_backtrace_display" */
+    fprintf(stderr, "Backtrace (displayed in process %s):\n", SIMIX_process_self_get_name());
+    for (int i = 1; i < e->used; i++)       /* no need to display "xbt_backtrace_display" */
       fprintf(stderr, "---> %s\n", e->bt_strings[i] + 4);
   }
 
@@ -106,7 +98,6 @@ void xbt_backtrace_display(xbt_ex_t * e)
   e->msg = NULL;
   xbt_ex_free(*e);
 #else
-
   XBT_ERROR("No backtrace on this arch");
 #endif
 }
@@ -119,29 +110,32 @@ void xbt_backtrace_display_current(void)
   xbt_backtrace_display(&e);
 }
 
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
-# include "backtrace_linux.c"
-#elif (defined(_XBT_WIN32) && defined (_M_IX86)) && !defined(__GNUC__)
-# include "backtrace_windows.c"
+#if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE)
+# include "src/xbt/backtrace_linux.c"
 #else
-# include "backtrace_dummy.c"
+# include "src/xbt/backtrace_dummy.c"
 #endif
 
 /** @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);
 
-  fprintf(stderr,
-          "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n"
+  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->msg,
+          xbt_binary_name, xbt_getpid(), xbt_ex_catname(e->category), e->value, e->msg,
           e->procname, thrower ? thrower : " in this process");
   XBT_CRITICAL("%s", e->msg);
   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 */
+  }
+
   if (!e->bt_strings)
     xbt_ex_setup_backtrace(e);
 
@@ -149,23 +143,41 @@ void xbt_ex_display(xbt_ex_t * e)
   if (e->used && e->bt_strings) {
     /* We have everything to build neat backtraces */
     int i;
+    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_ANONYMOUS { }
 
     fprintf(stderr, "\n");
-    for (i = 0; i < e->used; i++)
-      fprintf(stderr, "%s\n", e->bt_strings[i]);
-
+    for (i = 0; i < e->used; i++) {
+        
+      if (cutpath) {
+        char* p = e->bt_strings[i];
+        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 = malloc(length);
+
+        memcpy(dest, &p[0], length);
+        dest[length] = 0;
+
+        fprintf(stderr, "%s %s\n", dest, filename);
+
+        free(dest);
+      }
+      else {
+        fprintf(stderr, "%s\n", e->bt_strings[i]);
+      }
+    }
   } else
 #endif
-  {
-    fprintf(stderr,
-            "\n"
-            "**   In %s() at %s:%d\n"
-            "**   (no backtrace available)\n",
-            e->func, e->file, e->line);
-  }
+    fprintf(stderr, "\n"
+        "**   In %s() at %s:%d\n"
+        "**   (no backtrace available)\n", e->func, e->file, e->line);
 }
 
-
 /* default __ex_terminate callback function */
 void __xbt_ex_terminate_default(xbt_ex_t * e)
 {
@@ -175,22 +187,17 @@ void __xbt_ex_terminate_default(xbt_ex_t * e)
 
 /* the externally visible API */
 XBT_EXPORT_NO_IMPORT(xbt_running_ctx_fetcher_t) __xbt_running_ctx_fetch = &__xbt_ex_ctx_default;
-XBT_EXPORT_NO_IMPORT(ex_term_cb_t) __xbt_ex_terminate =
-    &__xbt_ex_terminate_default;
-
+XBT_EXPORT_NO_IMPORT(ex_term_cb_t) __xbt_ex_terminate = &__xbt_ex_terminate_default;
 
 void xbt_ex_free(xbt_ex_t e)
 {
-  int i;
-
   free(e.msg);
 
   if (e.bt_strings) {
-    for (i = 0; i < e.used; i++)
+    for (int i = 0; i < e.used; i++)
       free(e.bt_strings[i]);
     free(e.bt_strings);
   }
-  /* memset(e,0,sizeof(xbt_ex_t)); */
 }
 
 /** \brief returns a short name for the given exception category */
@@ -225,12 +232,10 @@ const char *xbt_ex_catname(xbt_errcat_t cat)
     return "io error";
   case vm_error:
     return "vm error";
-
   }
   return "INVALID ERROR";
 }
 
-
 #ifdef SIMGRID_TEST
 #include <stdio.h>
 #include "xbt/ex.h"
@@ -253,8 +258,7 @@ XBT_TEST_UNIT("controlflow", test_controlflow, "basic nested control flow")
         xbt_test_fail("M2: n=%d (!= 2)", n);
       n++;
       THROWF(unknown_error, 0, "something");
-    }
-    CATCH(ex) {
+    } CATCH(ex) {
       if (n != 3)
         xbt_test_fail("M3: n=%d (!= 3)", n);
       n++;
@@ -266,8 +270,7 @@ XBT_TEST_UNIT("controlflow", test_controlflow, "basic nested control flow")
         xbt_test_fail("M2: n=%d (!= 5)", n);
       n++;
       THROWF(unknown_error, 0, "something");
-    }
-    CATCH_ANONYMOUS {
+    } CATCH_ANONYMOUS {
       if (n != 6)
         xbt_test_fail("M3: n=%d (!= 6)", n);
       n++;
@@ -275,8 +278,7 @@ XBT_TEST_UNIT("controlflow", test_controlflow, "basic nested control flow")
       n++;
     }
     xbt_test_fail("MX: n=%d (shouldn't reach this point)", n);
-  }
-  CATCH(ex) {
+  } CATCH(ex) {
     if (n != 7)
       xbt_test_fail("M4: n=%d (!= 7)", n);
     n++;
@@ -292,8 +294,7 @@ XBT_TEST_UNIT("value", test_value, "exception value passing")
 
   TRY {
     THROWF(unknown_error, 2, "toto");
-  }
-  CATCH(ex) {
+  } CATCH(ex) {
     xbt_test_add("exception value passing");
     if (ex.category != unknown_error)
       xbt_test_fail("category=%d (!= 1)", (int)ex.category);
@@ -309,7 +310,7 @@ XBT_TEST_UNIT("variables", test_variables, "variable value preservation")
 {
   xbt_ex_t ex;
   int r1;
-  int _XBT_GNUC_UNUSED r2;
+  int XBT_ATTRIB_UNUSED r2;
   int v1;
   volatile int v2;
 
@@ -318,8 +319,7 @@ XBT_TEST_UNIT("variables", test_variables, "variable value preservation")
     r2 = 5678;
     v2 = 5678;
     THROWF(unknown_error, 0, "toto");
-  }
-  CATCH(ex) {
+  } CATCH(ex) {
     xbt_test_add("variable preservation");
     if (r1 != 1234)
       xbt_test_fail("r1=%d (!= 1234)", r1);
@@ -350,8 +350,7 @@ XBT_TEST_UNIT("cleanup", test_cleanup, "cleanup handling")
     if (v1 != 5678)
       xbt_test_fail("v1 = %d (!= 5678)", v1);
     c = 1;
-  }
-  CATCH(ex) {
+  } CATCH(ex) {
     if (v1 != 5678)
       xbt_test_fail("v1 = %d (!= 5678)", v1);
     if (!(ex.category == 1 && ex.value == 2 && !strcmp(ex.msg, "blah")))
@@ -362,7 +361,6 @@ XBT_TEST_UNIT("cleanup", test_cleanup, "cleanup handling")
     xbt_test_fail("xbt_ex_free not executed");
 }
 
-
 /*
  * The following is the example included in the documentation. It's a good
  * idea to check its syntax even if we don't try to run it.
@@ -376,37 +374,6 @@ static char *mallocex(int size)
 #define SMALLAMOUNT 10
 #define TOOBIG 100000000
 
-#if 0                           /* this contains syntax errors, actually */
-static void bad_example(void)
-{
-  struct {
-    char *first;
-  } *globalcontext;
-  ex_t ex;
-
-  /* BAD_EXAMPLE */
-  TRY {
-    char *cp1, *cp2, *cp3;
-
-    cp1 = mallocex(SMALLAMOUNT);
-    globalcontext->first = cp1;
-    cp2 = mallocex(TOOBIG);
-    cp3 = mallocex(SMALLAMOUNT);
-    strcpy(cp1, "foo");
-    strcpy(cp2, "bar");
-  }
-  TRY_CLEANUP {
-    free(cp3);
-    free(cp2);
-    free(cp1);
-  }
-  CATCH_ANONYMOUS {
-    printf("cp3=%s", cp3);
-    RETHROW;
-  }
-  /* end_of_bad_example */
-}
-#endif
 typedef struct {
   char *first;
 } global_context_t;