Deadlock while using boost::asio::deadline_timer i

2020-04-11 06:49发布

问题:

I am trying to use Boost-Deadlinetimer inside a DLL, which is loaded using boost::dll::shared_library. Following code-snippets are reduced to the essentials.

Example.h:

#include <boost/asio.hpp>
class Example  
{  
public:  
    Class() : m_timer(m_ioService) { } 
    virtual ~Class() { }  
    //...    
private:  
    boost::asio::io_service m_ioService;  
    boost::asio::deadline_timer m_timer;
    //...
};

Example.cpp:

#include "Example.h"
#include <boost/config.hpp>
//...
extern "C" BOOST_SYMBOL_EXPORT Example MyExample;
Example MyExample;

Main.cpp:

#include <boost/dll/Import.hpp>
//...
boost::dll::shared_library lib("Example.dll", boost::dll::load_mode::Default_mode);
//...

My Problem is that there is a deadlock while loading the compiled dll as long as m_timer is in the constructor's initialization list.

When replacing m_timer by a boost::shared_ptr and initializing that in the constructor (or a subsequent function), then there is no deadlock while loading the dll but a deadlock while unloading the dll.

Anyway, I cannot really use a global deadline timer object in a Windows dll.

回答1:

Windows has a LoaderLock which is held from the call to LoadLibrary until it returns.

This lock is used by the Windows system to ensure that the process remains stable, as cascaded DLLs are properly reference counted.

Globals which are created within a DLL, are constructed by dynamic initialization just before DllMain runs (DLL_PROCESS_ATTACH), and destroyed just after DllMain finishes (DLL_PROCESS_DETACH).

When you create a DLL with a global variable, you need to follow the rules in the link, and avoid...

  • Loading DLLs
  • Using Locks - cause of lock-inversion
  • Creating processes
  • Reading the registry
  • Creating/destroying threads
  • using the StringType functions.

The easiest way to cope with this would be having a separate initialize function which is called after LoadLibrary, and a Uninitialize function called before the final FreeLibrary where global variables are separately initialized.