fixes #730 nn_assert could print a backtrace
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0cf09e9..e1c55f4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -190,6 +190,7 @@
     nn_check_sym (CLOCK_MONOTONIC time.h NN_HAVE_CLOCK_MONOTONIC)
     nn_check_sym (atomic_cas_32 atomic.h NN_HAVE_ATOMIC_SOLARIS)
     nn_check_sym (AF_UNIX sys/socket.h NN_HAVE_UNIX_SOCKETS)
+    nn_check_sym (backtrace_symbols_fd execinfo.h NN_HAVE_BACKTRACE)
     nn_check_struct_member(msghdr msg_control sys/socket.h NN_HAVE_MSG_CONTROL)
     if (NN_HAVE_SEMAPHORE_RT OR NN_HAVE_SEMAPHORE_PTHREAD)
         add_definitions (-DNN_HAVE_SEMAPHORE)
diff --git a/perf/local_lat.c b/perf/local_lat.c
index 3d7e973..a1452a0 100644
--- a/perf/local_lat.c
+++ b/perf/local_lat.c
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -27,7 +28,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
+
+#include "../src/utils/err.c"
 
 int main (int argc, char *argv [])
 {
@@ -50,28 +52,28 @@
     rts = atoi (argv [3]);
 
     s = nn_socket (AF_SP, NN_PAIR);
-    assert (s != -1);
+    nn_assert (s != -1);
     opt = 1;
     rc = nn_setsockopt (s, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
-    assert (rc == 0);
+    nn_assert (rc == 0);
     rc = nn_bind (s, bind_to);
-    assert (rc >= 0);
+    nn_assert (rc >= 0);
 
     buf = malloc (sz);
-    assert (buf);
+    nn_assert (buf);
     memset (buf, 111, sz);
 
     for (i = 0; i != rts; i++) {
         nbytes = nn_recv (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
         nbytes = nn_send (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
     }
 
     free (buf);
 
     rc = nn_close (s);
-    assert (rc == 0);
+    nn_assert (rc == 0);
 
     return 0;
 }
diff --git a/perf/local_thr.c b/perf/local_thr.c
index b8ba1f6..a3f9fb3 100644
--- a/perf/local_thr.c
+++ b/perf/local_thr.c
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -25,9 +26,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 
 #include "../src/utils/stopwatch.c"
+#include "../src/utils/err.c"
 
 int main (int argc, char *argv [])
 {
@@ -53,20 +54,20 @@
     count = atoi (argv [3]);
 
     s = nn_socket (AF_SP, NN_PAIR);
-    assert (s != -1);
+    nn_assert (s != -1);
     rc = nn_bind (s, bind_to);
-    assert (rc >= 0);
+    nn_assert (rc >= 0);
 
     buf = malloc (sz);
-    assert (buf);
+    nn_assert (buf);
 
     nbytes = nn_recv (s, buf, sz, 0);
-    assert (nbytes == 0);
+    nn_assert (nbytes == 0);
 
     nn_stopwatch_init (&sw);
     for (i = 0; i != count; i++) {
         nbytes = nn_recv (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
     }
     total = nn_stopwatch_term (&sw);
     if (total == 0)
@@ -83,7 +84,7 @@
     free (buf);
 
     rc = nn_close (s);
-    assert (rc == 0);
+    nn_assert (rc == 0);
 
     return 0;
 }
diff --git a/perf/remote_lat.c b/perf/remote_lat.c
index 400468a..cde1869 100644
--- a/perf/remote_lat.c
+++ b/perf/remote_lat.c
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -27,9 +28,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
 #include "../src/utils/stopwatch.c"
+#include "../src/utils/err.c"
 
 int main (int argc, char *argv [])
 {
@@ -56,23 +57,23 @@
     rts = atoi (argv [3]);
 
     s = nn_socket (AF_SP, NN_PAIR);
-    assert (s != -1);
+    nn_assert (s != -1);
     opt = 1;
     rc = nn_setsockopt (s, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
-    assert (rc == 0);
+    nn_assert (rc == 0);
     rc = nn_connect (s, connect_to);
-    assert (rc >= 0);
+    nn_assert (rc >= 0);
 
     buf = malloc (sz);
-    assert (buf);
+    nn_assert (buf);
     memset (buf, 111, sz);
 
     nn_stopwatch_init (&sw);
     for (i = 0; i != rts; i++) {
         nbytes = nn_send (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
         nbytes = nn_recv (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
     }
     total = nn_stopwatch_term (&sw);
 
@@ -84,7 +85,7 @@
     free (buf);
 
     rc = nn_close (s);
-    assert (rc == 0);
+    nn_assert (rc == 0);
 
     return 0;
 }
diff --git a/perf/remote_thr.c b/perf/remote_thr.c
index 3b8f60c..82ca2f6 100644
--- a/perf/remote_thr.c
+++ b/perf/remote_thr.c
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -26,7 +27,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
+
+#include "../src/utils/err.c"
 
 int main (int argc, char *argv [])
 {
@@ -48,26 +50,26 @@
     count = atoi (argv [3]);
 
     s = nn_socket (AF_SP, NN_PAIR);
-    assert (s != -1);
+    nn_assert (s != -1);
     rc = nn_connect (s, connect_to);
-    assert (rc >= 0);
+    nn_assert (rc >= 0);
 
     buf = malloc (sz);
-    assert (buf);
+    nn_assert (buf);
     memset (buf, 111, sz);
 
     nbytes = nn_send (s, buf, 0, 0);
-    assert (nbytes == 0);
+    nn_assert (nbytes == 0);
 
     for (i = 0; i != count; i++) {
         nbytes = nn_send (s, buf, sz, 0);
-        assert (nbytes == (int)sz);
+        nn_assert (nbytes == (int)sz);
     }
 
     free (buf);
 
     rc = nn_close (s);
-    assert (rc == 0);
+    nn_assert (rc == 0);
 
     return 0;
 }
diff --git a/src/utils/err.c b/src/utils/err.c
index cdbfb47..e15148d 100644
--- a/src/utils/err.c
+++ b/src/utils/err.c
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -26,6 +27,28 @@
 #include "win.h"
 #endif
 
+#ifdef NN_HAVE_BACKTRACE
+#include <execinfo.h>
+
+void nn_backtrace_print (void)
+{
+    void *frames[50];
+    int size;
+    size = backtrace (frames, sizeof (frames) / sizeof (frames[0]));
+    if (size > 1) {
+        /*  Don't include the frame nn_backtrace_print itself. */
+        backtrace_symbols_fd (&frames[1], size-1, fileno (stderr));
+    }
+}
+
+/* XXX: Add Windows backtraces */
+
+#else
+void nn_backtrace_print (void)
+{
+}
+#endif
+
 #include <stdlib.h>
 
 void nn_err_abort (void)
@@ -187,4 +210,3 @@
 }
 
 #endif
-
diff --git a/src/utils/err.h b/src/utils/err.h
index 8864e68..fbaf65d 100644
--- a/src/utils/err.h
+++ b/src/utils/err.h
@@ -1,5 +1,6 @@
 /*
     Copyright (c) 2012 Martin Sustrik  All rights reserved.
+    Copyright 2016 Garrett D'Amore <garrett@damore.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"),
@@ -45,6 +46,7 @@
 #define nn_assert(x) \
     do {\
         if (nn_slow (!(x))) {\
+            nn_backtrace_print (); \
             fprintf (stderr, "Assertion failed: %s (%s:%d)\n", #x, \
                 __FILE__, __LINE__);\
             fflush (stderr);\
@@ -55,6 +57,7 @@
 #define nn_assert_state(obj, state_name) \
     do {\
         if (nn_slow ((obj)->state != state_name)) {\
+            nn_backtrace_print (); \
             fprintf (stderr, \
                 "Assertion failed: %d == %s (%s:%d)\n", \
                 (obj)->state, #state_name, \
@@ -68,6 +71,7 @@
 #define alloc_assert(x) \
     do {\
         if (nn_slow (!x)) {\
+            nn_backtrace_print (); \
             fprintf (stderr, "Out of memory (%s:%d)\n",\
                 __FILE__, __LINE__);\
             fflush (stderr);\
@@ -79,6 +83,7 @@
 #define errno_assert(x) \
     do {\
         if (nn_slow (!(x))) {\
+            nn_backtrace_print (); \
             fprintf (stderr, "%s [%d] (%s:%d)\n", nn_err_strerror (errno),\
                 (int) errno, __FILE__, __LINE__);\
             fflush (stderr);\
@@ -90,6 +95,7 @@
 #define errnum_assert(cond, err) \
     do {\
         if (nn_slow (!(cond))) {\
+            nn_backtrace_print (); \
             fprintf (stderr, "%s [%d] (%s:%d)\n", nn_err_strerror (err),\
                 (int) (err), __FILE__, __LINE__);\
             fflush (stderr);\
@@ -102,9 +108,11 @@
     do {\
         if (nn_slow (!(x))) {\
             char errstr [256];\
-            nn_win_error ((int) GetLastError (), errstr, 256);\
+            DWORD errnum = WSAGetLastError ();\
+            nn_backtrace_print (); \
+            nn_win_error ((int) errnum, errstr, 256);\
             fprintf (stderr, "%s [%d] (%s:%d)\n",\
-                errstr, (int) GetLastError (), __FILE__, __LINE__);\
+                errstr, (int) errnum, __FILE__, __LINE__);\
             fflush (stderr);\
             nn_err_abort ();\
         }\
@@ -115,9 +123,11 @@
     do {\
         if (nn_slow (!(x))) {\
             char errstr [256];\
-            nn_win_error (WSAGetLastError (), errstr, 256);\
+            DWORD errnum = WSAGetLastError ();\
+            nn_backtrace_print (); \
+            nn_win_error (errnum, errstr, 256);\
             fprintf (stderr, "%s [%d] (%s:%d)\n",\
-                errstr, (int) WSAGetLastError (), __FILE__, __LINE__);\
+                errstr, (int) errnum, __FILE__, __LINE__);\
             fflush (stderr);\
             nn_err_abort ();\
         }\
@@ -126,6 +136,7 @@
 /*  Assertion-like macros for easier fsm debugging. */
 #define nn_fsm_error(message, state, src, type) \
     do {\
+        nn_backtrace_print(); \
         fprintf (stderr, "%s: state=%d source=%d action=%d (%s:%d)\n", \
             message, state, src, type, __FILE__, __LINE__);\
         fflush (stderr);\
@@ -153,6 +164,7 @@
 NN_NORETURN void nn_err_abort (void);
 int nn_err_errno (void);
 const char *nn_err_strerror (int errnum);
+void nn_backtrace_print (void);
 
 #ifdef NN_HAVE_WINDOWS
 int nn_err_wsa_to_posix (int wsaerr);
@@ -160,4 +172,3 @@
 #endif
 
 #endif
-