Search code examples
c++mongodbmongo-cxx-drivermongo-c-driver

Mongocxx library segmentation fault


I'm trying to install the mongo-c-driver and mongo-cxx-driver in a Docker image, but when I run my C++ program it throws a Segmentation fault. Any ideas? Valgrind says it's mongo's fault.

I have some IOT devices and in my own computer they run just fine.

I'm using:

  • ubuntu:focal as base image
  • mongo-c-driver version 1.16.2 (also tried with 1.17 and 1.15)
  • mongo-cxx-driver version 3.5 (also tried with 3.6)
  • MongoDB server version 4.2.8
  • g++ version (Ubuntu 9.3.0-10ubuntu2) 9.3.0

Code:

std::string MongoDB::insertDocument(std::string database,
    std::string collection, bsoncxx::document::view_or_value document)
{
    try
    {
        mongocxx::uri uri(_connection_string);
        mongocxx::client conn(uri); // seg fault occurs here

        mongocxx::database db = conn[database];
        mongocxx::collection coll = db[collection];

        auto inserted = coll.insert_one(document.view());

        bsoncxx::oid oid = inserted->inserted_id().get_oid().value;
        return oid.to_string();
    }
    catch (const mongocxx::exception & e)
    {
        std::cerr << "WARNING: Unable to connect to MongoDB" << std::endl;
        return "UNKNOWN";
    }
}

Variable values:

_connection_string = "mongodb://burns"
database = "hopping"
collection = "executions"
document = 
{
    "created_at" : "2020.09.29 10:48:51",
    "hostname" : "XXXXX",
    "interface" : "wlp3s0mon",
    "schedule" : [ 1 ],
    "slot_size" : 200,
    "type" : "MOCK_NODE"
}

Log:

==213== Invalid read of size 8
==213==    at 0x5695C0A: mongoc_counter_clients_active_add (mongoc-counters.defs:37)
==213==    by 0x5695C0A: mongoc_counter_clients_active_inc (mongoc-counters.defs:37)
==213==    by 0x5695C0A: _mongoc_client_new_from_uri (mongoc-client.c:1101)
==213==    by 0x5318074: mongocxx::v_noabi::client::client(mongocxx::v_noabi::uri const&, mongocxx::v_noabi::options::client const&) (in /usr/local/lib/libmongocxx.so.3.5.0)
==213==    by 0x4B691D0: MongoDB::insertDocument(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bsoncxx::v_noabi::view_or_value<bsoncxx::v_noabi::document::view, bsoncxx::v_noabi::document::value>) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x4B69714: MongoDB::insertJSONDocument(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x4B61AD0: DataLogger::setExecutionParameters(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x1C232B: main (in /root/mock_node/build/mock_node)
==213==  Address 0x38 is not stack'd, malloc'd or (recently) free'd
==213== 
==213== 
==213== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==213==  Access not within mapped region at address 0x38
==213==    at 0x5695C0A: mongoc_counter_clients_active_add (mongoc-counters.defs:37)
==213==    by 0x5695C0A: mongoc_counter_clients_active_inc (mongoc-counters.defs:37)
==213==    by 0x5695C0A: _mongoc_client_new_from_uri (mongoc-client.c:1101)
==213==    by 0x5318074: mongocxx::v_noabi::client::client(mongocxx::v_noabi::uri const&, mongocxx::v_noabi::options::client const&) (in /usr/local/lib/libmongocxx.so.3.5.0)
==213==    by 0x4B691D0: MongoDB::insertDocument(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bsoncxx::v_noabi::view_or_value<bsoncxx::v_noabi::document::view, bsoncxx::v_noabi::document::value>) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x4B69714: MongoDB::insertJSONDocument(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x4B61AD0: DataLogger::setExecutionParameters(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /usr/local/lib/influx_logging/libinflux_logging.so)
==213==    by 0x1C232B: main (in /root/mock_node/build/mock_node)
==213==  If you believe this happened as a result of a stack
==213==  overflow in your program's main thread (unlikely but
==213==  possible), you can try to increase the size of the
==213==  main thread stack using the --main-stacksize= flag.
==213==  The main thread stack size used in this run was 8388608.
==213== 
==213== HEAP SUMMARY:
==213==     in use at exit: 123,339 bytes in 262 blocks
==213==   total heap usage: 3,719 allocs, 3,457 frees, 367,254 bytes allocated
==213== 
==213== LEAK SUMMARY:
==213==    definitely lost: 400 bytes in 1 blocks
==213==    indirectly lost: 6,752 bytes in 20 blocks
==213==      possibly lost: 576 bytes in 2 blocks
==213==    still reachable: 115,611 bytes in 239 blocks
==213==         suppressed: 0 bytes in 0 blocks
==213== Rerun with --leak-check=full to see details of leaked memory
==213== 
==213== For lists of detected and suppressed errors, rerun with: -s
==213== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

Ps: mock_node is my executable and influxdb-logging is a library of mine.

Thank you very much, I have no idea what could be causing this...


Solution

  • From Tutorial for mongocxx:

    IMPORTANT: Before making any connections, you need to create one and only one instance of mongocxx::instance. This instance must exist for the entirety of your program.

    So, you can add this as a static member of your MongoDB class:

    header

    class MongoDB {
        //...
    private:
         static mongocxx::instance inst;
    };
    

    impl

    mongocxx::instance MongoDB::inst{};
    

    Here's an example where I connect to the the default mongodb server (mongodb://localhost:27017), use the database dbted and the collection movie, both of which previously created using the mongo cli.

    I added a method to get a mongocxx::cursor to all documents in the collection.

    #include <bsoncxx/builder/stream/document.hpp>
    #include <bsoncxx/json.hpp>
    
    #include <mongocxx/client.hpp>
    #include <mongocxx/exception/exception.hpp>
    #include <mongocxx/instance.hpp>
    #include <mongocxx/uri.hpp>
    
    #include <iostream>
    
    class MongoDB {
    public:
        MongoDB() :
            client{mongocxx::uri{"mongodb://localhost:27017"}},
            db{client["dbted"]},
            coll{db["movie"]} 
        {}
    
        mongocxx::cursor all() { return coll.find({}); }
    
    private
        mongocxx::client client;
        mongocxx::database db;
        mongocxx::collection coll;
    
        static mongocxx::instance inst;
    };
    
    mongocxx::instance MongoDB::inst{};
    
    int main() {
        try {
            MongoDB db;
    
            std::cout << "Connected successfully\n";
    
            for(auto doc : db.all()) {
                std::cout << bsoncxx::to_json(doc) << '\n';
            }
    
        } catch(const std::exception& ex) {
            std::cerr << "Exception: " << ex.what() << std::endl;
            return 1;
        }
    }