[SERVER-5852] freebsd 64-bit backtrace segfaults Created: 16/May/12  Updated: 28/Oct/15  Resolved: 08/Jun/12

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1.2

Type: Bug Priority: Major - P3
Reporter: Eric Milkie Assignee: Andy Schwerin
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

FreeBSD 64-bit


Operating System: ALL
Participants:

 Description   

If you run 'test', it typically prints stack traces as part of 'cursor' test. 32-bit works fine but 64-bit crashes with a segfault in libexecinfo in the backtrace() function.



 Comments   
Comment by Andy Schwerin [ 10/Jul/12 ]

Existing tests exercised this bug.

Comment by Eric Milkie [ 27/Jun/12 ]

Sorry Sam, I forgot Doc Changes should have gone to None. We ended up not using libunwind for FreeBSD after all, so the library dependency is back to libexecinfo.

Comment by Andy Schwerin [ 08/Jun/12 ]

Just need to use frame pointers in 64-bit FreeBSD, so their unwinder will work.

Comment by auto [ 08/Jun/12 ]

Author:

{u'login': u'andy10gen', u'name': u'Andy Schwerin', u'email': u'schwerin@10gen.com'}

Message: SERVER-5852: Use frame-pointers in 64-bit FreeBSD builds.

This makes execinfo:backtrace() work, and should have a minimal impact on
performance.
Branch: master
https://github.com/mongodb/mongo/commit/57f64fe508006d82b5af4c1460a938bfc4396331

Comment by auto [ 24/May/12 ]

Author:

{u'login': u'milkie', u'name': u'Eric Milkie', u'email': u'milkie@10gen.com'}

Message: Revert "SERVER-5852 use libunwind routines for backtrace on freebsd"

This reverts commit e6f9efc3c372f5bc8871df838c6e891117655a88.

This may be resubmitted as a generic replacement for backtrace()
on all platforms, rather than just FreeBSD.
Branch: master
https://github.com/mongodb/mongo/commit/a7be5e92b29cf21ccee24ab26fbdb8c76082eb2c

Comment by Eric Milkie [ 24/May/12 ]

change documentation for 'building freebsd' to mention that it needs libunwind installed instead of libexecinfo now

Comment by auto [ 24/May/12 ]

Author:

{u'login': u'milkie', u'name': u'Eric Milkie', u'email': u'milkie@10gen.com'}

Message: SERVER-5852 use libunwind routines for backtrace on freebsd
Branch: master
https://github.com/mongodb/mongo/commit/e6f9efc3c372f5bc8871df838c6e891117655a88

Comment by Eric Milkie [ 23/May/12 ]

I got something working, will commit soon

Comment by Daniel Crosta [ 22/May/12 ]

Here is a proof-of-concept for printing stack information on FreeBSD using libunwind:

(add to stacktrace.cpp after the first #if block)

diff --git a/src/mongo/util/stacktrace.cpp b/src/mongo/util/stacktrace.cpp
index 4e46872..7fc1057 100644
--- a/src/mongo/util/stacktrace.cpp
+++ b/src/mongo/util/stacktrace.cpp
@@ -34,6 +34,33 @@ namespace mongo {
     }
 }
 
+#elif MONGO_HAVE_UNWIND_BACKTRACE
+
+// This makes libunwind only work for within the
+// current process, but that's what we want anyway.
+#define UNW_LOCAL_ONLY
+
+#include <libunwind.h>
+
+namespace mongo {
+    static const int maxBackTraceFrames = 20;
+
+    void printStackTrace( std::ostream &os ) {
+        unw_context_t stack;
+        unw_cursor_t cursor;
+        unw_word_t ip, sp;
+
+        unw_getcontext(&stack);
+        unw_init_local(&cursor, &stack);
+
+        for ( int depth = 0; depth < maxBackTraceFrames, unw_step(&cursor) != 0; ++depth ) {
+            unw_get_reg(&cursor, UNW_REG_IP, &ip);
+            unw_get_reg(&cursor, UNW_REG_SP, &sp);
+            os << " ip: " << (long)ip << ", sp: " << (long)sp << std::endl;
+        }
+    }
+}
+
 #else
 
 namespace mongo {   

SConstruct also needs to check for libunwind, and set the appropriate macro:

diff --git a/SConstruct b/SConstruct
index b349f4e..4c8f528 100644
--- a/SConstruct
+++ b/SConstruct
@@ -789,7 +789,10 @@ def doConfigure(myenv):
     if solaris or conf.CheckDeclaration('clock_gettime', includes='#include <time.h>'):
         conf.CheckLib('rt')
 
-    if (conf.CheckCXXHeader( "execinfo.h" ) and
+    if freebsd and conf.CheckCXXHeader( "unwind.h" ):
+        myenv.Append( CPPDEFINES=[ "MONGO_HAVE_UNWIND_BACKTRACE" ] )
+
+    elif (conf.CheckCXXHeader( "execinfo.h" ) and
         conf.CheckDeclaration('backtrace', includes='#include <execinfo.h>') and
         conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>')):
 
@@ -808,9 +811,11 @@ def doConfigure(myenv):
         if not conf.CheckLib( v8_lib_choices ):
             Exit(1)
 
-    # requires ports devel/libexecinfo to be installed
+    # requires ports devel/libexecinfo or devel/libunwind to be installed
     if freebsd or openbsd:
-        if not conf.CheckLib("execinfo"):
+        # CheckLib actually sets the -l argument, so check in the
+        # order of precedence.
+        if not (conf.CheckLib("unwind") or conf.CheckLib("execinfo")):
             Exit(1)
 
     # 'tcmalloc' needs to be the last library linked. Please, add new libraries before this 

Comment by Daniel Crosta [ 18/May/12 ]

$ pkg_info | grep libexecinfo
libexecinfo-1.1_3   A library for inspecting program's backtrace

I can file a bug with FreeBSD, but it would be nice if we had a small reproducing test case to submit with it – can you help me make one (or make one yourself?)

Comment by Eric Milkie [ 18/May/12 ]

@dcrosta, do we have version 1.1_3 of libexecinfo? There were apparently some 64-bit fixes made in the latest version that 1.1_2 doesn't have.

Generated at Thu Feb 08 03:10:03 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.