Print error rather than abort
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 13 Nov 2014 19:58:22 +0000 (14:58 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 13 Nov 2014 19:58:22 +0000 (14:58 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Makefile.am
tests/benchmark/Makefile.am
tests/regression/Makefile.am
tests/unit/Makefile.am
urcu-checker.c

index 7ead5f06283ec8d96521b159898ee03cef48ef6f..8fbf11d9d82f695c6210ca8aad90ee63219be013 100644 (file)
@@ -59,6 +59,7 @@ lib_LTLIBRARIES = liburcu-common.la \
 #
 liburcu_common_la_SOURCES = wfqueue.c wfcqueue.c wfstack.c $(COMPAT) \
                urcu-checker.c
+liburcu_common_la_LDFLAGS = -ldl
 
 liburcu_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
 liburcu_la_LIBADD = liburcu-common.la
index b8cf35d054d8afe72cb1e365ebc9444e608eb8c6..17c1fe027edebf27c5ae4ce39a60528fdc3d666c 100644 (file)
@@ -1,7 +1,7 @@
 if !LIBC_INCLUDES_PTHREAD
 AM_LDFLAGS=-lpthread
 endif
-AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g
+AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g -ldl
 
 noinst_PROGRAMS = test_urcu test_urcu_dynamic_link test_urcu_timing \
        test_urcu_signal test_urcu_signal_dynamic_link test_urcu_signal_timing \
index 354ad1a9f69b2e6d44b36a5c9f92dd90fcfa23e3..8701e9bb503c707b318c06ead28cca57377beedb 100644 (file)
@@ -1,7 +1,7 @@
 if !LIBC_INCLUDES_PTHREAD
 AM_LDFLAGS=-lpthread
 endif
-AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g
+AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g -ldl
 
 noinst_PROGRAMS = test_urcu_fork \
        rcutorture_urcu \
index cd40b399372919f707e99f2968c616af547198e3..97275a64d47a6fd4390d40b7cfc148869e4e3caf 100644 (file)
@@ -1,7 +1,7 @@
 if !LIBC_INCLUDES_PTHREAD
 AM_LDFLAGS=-lpthread
 endif
-AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g
+AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/tests/common -g -ldl
 
 noinst_PROGRAMS = test_uatomic \
        test_urcu_multiflavor \
index 234bd9bc68e72ffb45ef5ef12e4ffe6723b6f3e4..cd4721d3cd95f1a1a4f2454dd5c19b99c5807ff6 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/*
+ * NOTE: build application with -rdynamic -ldl -lurcu-common.
+ */
+
+#define _GNU_SOURCE
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <execinfo.h>
+#include <dlfcn.h>
+#include <sys/types.h>
 #include <urcu/urcu-checker.h>
 #include <urcu/tls-compat.h>
 
-#define URCU_DEBUG_STACK_LEN   10
+#define URCU_DEBUG_STACK_LEN           10
+#define DEFAULT_PRINT_BACKTRACE_LEN    5
+#define BACKTRACE_LEN                  16
+
+#ifdef __linux__
+#include <syscall.h>
+#endif
+
+#if defined(_syscall0)
+_syscall0(pid_t, gettid)
+#elif defined(__NR_gettid)
+#include <unistd.h>
+static inline pid_t gettid(void)
+{
+       return syscall(__NR_gettid);
+}
+#else
+#include <sys/types.h>
+#include <unistd.h>
+
+/* Fall-back on getpid for tid if not available. */
+static inline pid_t gettid(void)
+{
+       return getpid();
+}
+#endif
+
+#define err_printf(fmt, args...) \
+       fprintf(stderr, "[urcu-checker %ld/%ld] "  fmt, \
+               (long) getpid(), (long) gettid(), ## args)
 
 struct urcu_debug_entry {
        void *ip;
@@ -39,8 +76,72 @@ struct urcu_debug_stack {
        int stackend;
 };
 
+struct backtrace {
+       void *ptrs[BACKTRACE_LEN];
+       char **symbols;
+};
+
 static DEFINE_URCU_TLS(struct urcu_debug_stack, rcu_debug_stack);
 
+static volatile int print_backtrace_len = DEFAULT_PRINT_BACKTRACE_LEN;
+
+/*
+ * Allocates a string, or NULL.
+ */
+static
+char *get_symbol(const void *caller)
+{
+       Dl_info info;
+       char *caller_symbol;
+
+       if (caller && dladdr(caller, &info) && info.dli_sname) {
+               caller_symbol = strdup(info.dli_sname);
+       } else {
+               caller_symbol = NULL;
+       }
+       return caller_symbol;
+}
+
+static inline __attribute__((always_inline))
+void save_backtrace(struct backtrace *bt)
+{
+       memset(bt, 0, sizeof(*bt));
+       (void) backtrace(bt->ptrs, BACKTRACE_LEN);
+       bt->symbols = backtrace_symbols(bt->ptrs, BACKTRACE_LEN);
+}
+
+static
+void free_backtrace(struct backtrace *bt)
+{
+       free(bt->symbols);
+}
+
+static
+void print_bt(struct backtrace *bt)
+{
+       int j;
+       unsigned int empty = 1;
+
+       for (j = 0; j < BACKTRACE_LEN; j++) {
+               if (bt->ptrs[j]) {
+                       empty = 0;
+                       break;
+               }
+       }
+       if (empty)
+               return;
+
+       err_printf("[backtrace]\n");
+       for (j = 0; j < BACKTRACE_LEN && j < print_backtrace_len; j++) {
+               if (!bt->ptrs[j])
+                       continue;
+               if (bt->symbols)
+                       err_printf(" %p <%s>\n", bt->ptrs[j], bt->symbols[j]);
+               else
+                       err_printf(" %p\n", bt->ptrs[j]);
+       }
+}
+
 void rcu_read_lock_debug(void)
 {
        struct urcu_debug_stack *r = &URCU_TLS(rcu_debug_stack);
@@ -61,8 +162,13 @@ void rcu_read_ongoing_check_debug(const char *func)
        struct urcu_debug_stack *r = &URCU_TLS(rcu_debug_stack);
 
        if (r->stackend == 0) {
-               fprintf(stderr, "URCU LOCKED CHECK failure: %p\n",
-                       __builtin_return_address(0));
-               abort();
+               struct backtrace bt;
+
+               err_printf("rcu_dereference() used outside of critical section at %p <%s>\n",
+                       __builtin_return_address(0),
+                       get_symbol(__builtin_return_address(0)));
+               save_backtrace(&bt);
+               print_bt(&bt);
+               free_backtrace(&bt);
        }
 }
This page took 0.028333 seconds and 4 git commands to generate.