Friday, December 4, 2015

MongoDB 3.0.7 segmentation fault on ARM

Updates (2015-12-28): mongodb-3.2.0-3-armv7h of Arch Linux ARM ssems to be working fine.


The latest stable version (3.0.7) of MongoDB is having problem on Arch Linux ARM platforms.

Out of curiosity, I checked out the code from github and tried to compile and reproduce it. The segmentation fault seems to be caused by std::map.  Here is the gdb backtrace:

#0  std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0xad3e28, 
    __str=<error reading variable: Cannot access memory at address 0x0>)
    at /build/gcc/src/gcc-build/armv7l-unknown-linux-gnueabihf/libstdc++-v3/include/bits/basic_string.tcc:617
#1  0x00459b08 in std::pair<std::string const, mongo::optionenvironment::Value>::pair<std::string const&, 0u>(std::tuple<std::string const&>&, std::tuple<>&, std::_Index_tuple<0u>, std::_Index_tuple<>) (__tuple2=<synthetic pointer>, 
    __tuple1=..., this=0x0) at /usr/include/c++/5.2.0/tuple:1172
#2  std::pair<std::string const, mongo::optionenvironment::Value>::pair<std::string const&>(std::piecewise_construct_t, std::tuple<std::string const&>, std::tuple<>) (__second=..., __first=..., this=0x0)
    at /usr/include/c++/5.2.0/tuple:1161
#3  __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> > >::construct<std::pair<std::string const, mongo::optionenvironment::Value>, std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::pair<std::string const, mongo::optionenvironment::Value>*, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (__p=0x0, this=0xbefff558)
    at /usr/include/c++/5.2.0/ext/new_allocator.h:120
#4  std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> > > >::_S_construct<std::pair<std::string const, mongo::optionenvironment::Value>, std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::allocator<std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> > >&, std::pair<std::string const, mongo::optionenvironment::Value>*, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (
    __p=<optimized out>, __a=...)
    at /usr/include/c++/5.2.0/bits/alloc_traits.h:256
#5  std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> > > >::construct<std::pair<std::string const, mongo::optionenvironment::Value>, std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::allocator<std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> > >&, std::pair<std::string const, mongo::optionenvironment::Value>*, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (__p=<optimized out>, 
    __a=...) at /usr/include/c++/5.2.0/bits/alloc_traits.h:402
#6  std::_Rb_tree<std::string, std::pair<std::string const, mongo::optionenvironment::Value>, std::_Select1st<std::pair<std::string const, mongo::optionenvironment::Value> >, std::less<std::string>, std::allocator<std::pair<std::string const, mongo::optionenvironment::Value> > >::_M_construct_node<std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::_Rb_tree_node<std::pair<std::string const, mongo::optionenvironment::Value> >*, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (
    __node=0xad3e18, this=0xbefff558)
    at /usr/include/c++/5.2.0/bits/stl_tree.h:529
#7  std::_Rb_tree<std::string, std::pair<std::string const, mongo::optionenvironment::Value>, std::_Select1st<std::pair<std::string const, mongo::optionenvironment::Value> >, std::less<std::string>, std::allocator<std::pair<std::string const, mongo::optionenvironment::Value> > >::_M_create_node<std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (
    this=0xbefff558) at /usr/include/c++/5.2.0/bits/stl_tree.h:546
#8  std::_Rb_tree<std::string, std::pair<std::string const, mongo::optionenvironment::Value>, std::_Select1st<std::pair<std::string const, mongo::optionenvironment::Value> >, std::less<std::string>, std::allocator<std::pair<std::string const, mongo::optionenvironment::Value> > >::_M_emplace_hint_unique<std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::_Rb_tree_const_iterator<std::pair<std::string const, mongo::optionenvironment::Value> >, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (this=0xbefff558, __pos=...)
    at /usr/include/c++/5.2.0/bits/stl_tree.h:2170
#9  0x0046225c in std::map<std::string, mongo::optionenvironment::Value, std::less<std::string>, std::allocator<std::pair<std::string const, mongo::optionenvironment::Value> > >::operator[] (__k="authenticationDatabase", this=0xbefff4c4)
    at /usr/include/c++/5.2.0/bits/stl_map.h:483
#10 mongo::optionenvironment::OptionSection::getDefaults (this=0xbefff51c, 
    this@entry=0xad4038, values=0xbefff4c4, values@entry=0xbefff558)
    at src/mongo/util/options_parser/option_section.cpp:508
#11 0x00462134 in mongo::optionenvironment::OptionSection::getDefaults (
    this=0xbefff550, this@entry=0xbefff68c, values=0x4, 
    values@entry=0xbefff558)
    at src/mongo/util/options_parser/option_section.cpp:514
#12 0x0046984c in mongo::optionenvironment::OptionsParser::addDefaultValues (
    this=this@entry=0xab5750 <mongo::optionenvironment::startupOptions>, 
    options=..., 
    environment=0xab5704 <mongo::optionenvironment::startupOptionsParsed>, 
    environment@entry=0x474934 <mongo::optionenvironment::_mongoInitializerFunction_StartupOptions_Parse(mongo::InitializerContext*)+84>)
    at src/mongo/util/options_parser/options_parser.cpp:845
#13 0x0046edf8 in mongo::optionenvironment::OptionsParser::run (
    this=0xab5750 <mongo::optionenvironment::startupOptions>, 
    this@entry=0xbefff79c, options=..., 
Python Exception <class 'ValueError'> Cannot find type const std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Rep_type: 
    argv=std::vector of length 2, capacity 2 = {...}, 
    env=std::map with 21 elements, 
    environment=0xab5704 <mongo::optionenvironment::startupOptionsParsed>)
    at src/mongo/util/options_parser/options_parser.cpp:1012
#14 0x00474934 in mongo::optionenvironment::_mongoInitializerFunction_StartupOptions_Parse (context=0xbefff81c)
    at src/mongo/util/options_parser/options_parser_init.cpp:46
#15 0x0025eed4 in std::_Function_handler<mongo::Status (mongo::InitializerContext*), mongo::Status (*)(mongo::InitializerContext*)>::_M_invoke(std::_Any_data const&, mongo::InitializerContext*&&) (__functor=..., __args#0=<optimized out>)
    at /usr/include/c++/5.2.0/functional:1857
#16 0x0025f330 in std::function<mongo::Status (mongo::InitializerContext*)>::operator()(mongo::InitializerContext*) const (
    __args#0=<error reading variable: Cannot access memory at address 0x0>, 
    this=0xbefff80c) at /usr/include/c++/5.2.0/functional:2271
#17 mongo::Initializer::execute (this=0xab3dc0 <mongo::getGlobalInitializer()::theGlobalInitializer>, 
    Python Exception <class 'ValueError'> Cannot find type const mongo::InitializerContext::EnvironmentMap::_Rep_type: args=std::vector of length 2, capacity 2 = {...}, env=std::map with 21 elements) at src/mongo/base/initializer.cpp:58
#18 0x0025f8cc in mongo::runGlobalInitializers (
    Python Exception <class 'ValueError'> Cannot find type const mongo::InitializerContext::EnvironmentMap::_Rep_type: 
    args=std::vector of length 2, capacity 2 = {...}, 
    env=std::map with 21 elements) at src/mongo/base/initializer.cpp:71
#19 0x0025fb30 in mongo::runGlobalInitializers (argc=argc@entry=2, 
    argv=argv@entry=0xbefffc64, envp=<optimized out>, envp@entry=0xbefffc70)
    at src/mongo/base/initializer.cpp:90
#20 0x002600a0 in mongo::runGlobalInitializersOrDie (argc=argc@entry=2, 
    argv=argv@entry=0xbefffc64, envp=envp@entry=0xbefffc70)
    at src/mongo/base/initializer.cpp:94
#21 0x0025332c in _main (argc=argc@entry=2, argv=argv@entry=0xbefffc64, 
    envp=envp@entry=0xbefffc70) at src/mongo/shell/dbshell.cpp:601
#22 0x0023aeac in main (argc=2, argv=0xbefffc64, envp=0xbefffc70)
    at src/mongo/shell/dbshell.cpp:924



From the getDefaults function in src/mongo/util/options_parser/option_section.cpp, the operator[] of std::map seems caused the failure when allocating new node:



    Status OptionSection::getDefaults(std::map<Key, Value>* values) const {

        std::list<OptionDescription>::const_iterator oditerator;
        for (oditerator = _options.begin(); oditerator != _options.end(); oditerator++) {
            if (!oditerator->_default.isEmpty()) {
                (*values)[oditerator->_dottedName] = oditerator->_default;
            }
        }

        std::list<OptionSection>::const_iterator ositerator;
        for (ositerator = _subSections.begin(); ositerator != _subSections.end(); ositerator++) {
            ositerator->getDefaults(values);
        }

        return Status::OK();
    }

Haven't figured out why.  But using the equivalent insert seems to be able to get around the issue.

-            (*values)[oditerator->_dottedName] = oditerator->_default;
+            //(*values)[oditerator->_dottedName] = oditerator->_default;
+            (*((values->insert(make_pair(oditerator->_dottedName, std::map<Key, Value>::mapped_type()))).first)).second = oditerator->_default;


Updates (2015-12-06): Building MongoDb with "--opt=off" (i.e. using -O0 instead of -O3") also works. Using g++ 5.2.0

No comments: