[CXX-840] Infinite wait in mongo 1.0.7 client if mongo::client::shutdown not explicitly called Created: 09/Feb/16  Updated: 23/Mar/16  Resolved: 23/Mar/16

Status: Closed
Project: C++ Driver
Component/s: Implementation
Affects Version/s: legacy-1.0.3, legacy-1.0.7
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Steve Ahlgren Assignee: Mira Carey
Resolution: Incomplete Votes: 0
Labels: legacy-cxx
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Zip Archive mongo_shutdown_defect.zip    

 Description   

Hi All,

Since updating from 2.x to 3.x, we've experienced significant difficultly with the new client driver requiring the explicit calls to mongo::client::initialize and mongo::client::shutdown, with a fatal infinite wait in the replica set monitor watcher if mongo::client::shutdown is not called explicitly.

We use Mongo in a shared library (dll) that is consumed by a number of clients, and in this scenario it's not straightforward to call mongo::client::shutdown from the parent executable. When the executable dies and the mongo wrapper DLL unloads, the mongo client driver's threads are terminated before the destructor for the replica set monitor watcher is called. When its destructor is called, it waits on a condition variable that will never be set, as the thread is already gone.

There are several possible workarounds and refactoring that could happen in the client driver.

But the main question is what's the best practice for wrapping the new Mongo driver in a dll used by a number of consumers? The current driver implementation makes this difficult if not impossible, so any advice would be appreciated.

An example app package is attached showing an exe calling a dll containing Mongo functionality.

Thank you kindly in advance,
Steve A.



 Comments   
Comment by Andrew Morrow (Inactive) [ 19/Mar/16 ]

Hi sga - Is there anything further we can help you with regarding this ticket? If so, please let us know, otherwise we will close this out.

Comment by Andrew Morrow (Inactive) [ 20/Feb/16 ]

Hi sga -

I'd like to better understand the issue you are having and why DLLs are problematic for you. I'm not at all as familiar with the mechanics of DLLs as I am with ELF shared objects, and I'm sort of reasoning by analogy with those, so apologies if I've got something wrong - I'm not a Windows expert, really.

I would expect that during process teardown destructors for objects of file scope in a DLL are executed. I would also expect that if foo.dll depends on bar.dll, that the destruction of global objects in bar.dll would be sequenced before the destruction of global objects in foo.dll.

So, we have three things in play, really: the application (lets call it app.exe), the DLL that uses mongoclient.dll (lets call it user.dll), and we have the mongoclient.dll itself. I'm imagining that app.exe depends on user.dll, which in turn depends on mongoclient.dll.

I would imagine that it a file, call it user.cpp, that was compiled into user.dll contained the following code

namespace {
    // Could use std::unique_ptr if we are using C++11
    std::shared_ptr<mongo::GlobalInstance> instance;
}
 
void setup_mongo_client(const mongo::client::Options& options) {
    instance.reset(new mongo::GlobalInstance(options);
}

That when app.exe terminated, the destructor of instance above would be sequenced before the termination of mongoclient.dll.

Would something like that not work?

Comment by Steve Ahlgren [ 09/Feb/16 ]

Hi Jason,

Thank you for the quick response. We will definitely consider the new driver.

Best,
Steve A.

Comment by Mira Carey [ 09/Feb/16 ]

Steve,

As you've noted, the legacy C++ driver isn't very amenable to wrapping. This is a natural consequence of how it came to be; as a series of improvements to code lifted directly out of the main mongodb source code. Unfortunately, that's also unlikely to change, as the legacy driver is no longer under active feature development and new feature support will be focused in our new C++11 driver.

If you're looking for a best practice to wrap up a connection to mongodb in a dll, I'd recommend that you consider our new C++11 driver, or its backend implementation (libmongoc). The C++11 driver offers a modern interface and the promise of future support, while the C driver offers a barebones implementation and a commitment to a stable ABI. While there is a notion of a global instance for our new C++ driver, and an init() / cleanup() pair for the c driver, they manage far more simplistic initialization and don't own anything like a background thread.

Regards,
Jason

Generated at Wed Feb 07 22:00:31 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.