c++mongodbapic++11mongodb-c

Mongodb C++11 API errno interference


It seems that a lot of mongodb c++11 functions change the system errno code to 11 (EWOULDBLOCK / EAGAIN). This is currently interfering with the rest of my program. I have a couple of questions:

Below is an example showing how pervasive the changing in errno is. The example is adapted from: https://www.mongodb.com/blog/post/introducing-new-c-driver?jmp=docs&_ga=1.90709144.367237569.1438109079

#include <iostream>

#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>

#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>

int main(int, char**) {
    errno = 0;
    int counter(0);
    std::string str;

    mongocxx::instance inst{};
    mongocxx::client conn{};

    bsoncxx::builder::stream::document document{};

    auto collection = conn["testdb"]["testcollection"];
    document << "hello" << "world";

    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    collection.insert_one(document.view());
    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    errno = 0;

    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    collection.insert_one(document.view());
    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    errno = 0;

    auto cursor = collection.find({});

    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    for (auto&& doc : cursor) {
        if (errno) {
            printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
            errno = 0;
        }

        str = bsoncxx::to_json(doc);
        //std::cout << str << std::endl;
        printf("counter: %i\n",counter++);
    }

    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
    collection.drop();
    printf("errno %i ... %s:%i\n", errno, __FILE__, __LINE__);
}

Results in the following output:

errno 0 ... hellomongo.cpp:22
errno 11 ... hellomongo.cpp:24
errno 0 ... hellomongo.cpp:27
errno 11 ... hellomongo.cpp:29
errno 0 ... hellomongo.cpp:34
errno 11 ... hellomongo.cpp:37
counter: 0
counter: 1
errno 0 ... hellomongo.cpp:46
errno 11 ... hellomongo.cpp:48

Solution

  • In general, you should expect that nearly any call into pretty much any library can cause errno to change.

    Internally, the C++11 driver is built above the C driver, which makes calls into the socket(7) subsytem, which sets errno. In particular, the C driver library makes non-blocking socket IO calls, which explains the EWOULDBLOCK/EAGAIN values that you are observing in errno.

    In general, good practice with errno requires that you capture the errno value immediately after invoking the function for which you want to extract detailed error information. Intervening calls are likely to reset it.