Boost logo

Boost :

From: JOLY Loic (loic.joly_at_[hidden])
Date: 2003-12-12 12:27:34


Dear boosters,

We have a problem when trying to launch a boost thread from a Windows DLL.

If we modify the code to have it all in the main program, it works as
intended, but here, when the trhead is launched from the DLL, creating
the thread object hangs.

I kwon that boost::thread plays with DLL to implement TLS, and I wonder
if this might create difficulties in our case ?

Here is an example code (I apologise for its length. If some people
request it, I can send an e-mail with the full source code and visual
C++6.0 project) :

///////////////////////////////////////////////////
// Main program :

//
// testBoostThread.cpp : Defines the entry point for the console
application.
//
#include <windows.h>
#include <lmerr.h> // NERR_BASE, MAX_NERR
#include <string>
#include <iostream>

#ifdef _DEBUG
#define FILENAME "testBoostThreadDll/Debug/testBoostThreadDll.dll"
#else // _DEBUG
#define FILENAME "testBoostThreadDll/Release/testBoostThreadDll.dll"
#endif // !_DEBUG

std::string errorText(unsigned long dwLastError)
{
        std::string toReturn;

     HMODULE hModule = NULL; // default to system source
     LPSTR MessageBuffer;
     DWORD dwBufferLength;

     DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
         FORMAT_MESSAGE_IGNORE_INSERTS |
         FORMAT_MESSAGE_FROM_SYSTEM ;

     if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
         hModule = LoadLibraryEx(
             TEXT("netmsg.dll"),
             NULL,
             LOAD_LIBRARY_AS_DATAFILE
             );

         if(hModule != NULL)
             dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
     }

//
// Call FormatMessage() to allow for message
// text to be acquired from the system
// or from the supplied module handle.
//

     if(dwBufferLength = FormatMessageA(
         dwFormatFlags,
         hModule, // module to get message from (NULL == system)
         dwLastError,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
         (LPSTR) &MessageBuffer,
         0,
         NULL
         ))
     {
         toReturn = MessageBuffer;

     //
     // Free the buffer allocated by the system.
     //
         LocalFree(MessageBuffer);
     }

//
// If we loaded a message source, unload it.
//
     if(hModule != NULL)
         FreeLibrary(hModule);

        return toReturn;
}

int main(int argc, char* argv[])
{
        HMODULE hModule = ::LoadLibrary(argv[1] ? argv[1] : FILENAME);
        if(!hModule)
        {
                std::cout << errorText(GetLastError()).c_str() << std::endl;
                return -1;
        }

        ::Sleep(2000);
        ::FreeLibrary(hModule);

        return 0;
}

/////////////////////////////////////////////////
// DLL

//
// testBoostTreadDll.cpp
//
#include <windows.h>

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>

class DrDT
{
public:
        virtual ~DrDT()
        {
                thrd->join();
                delete thrd;

        };
        DrDT()
        {
                std::cout << "Hello World from DrDT." << std::endl;
            thrd = new boost::thread(boost::bind(&DrDT::run, this));
        };

        void run()
        {
                for(int i = 0; i < 10; ++i)
                        std::cout << "Hello World #" << i << "." << std::endl;
        }

        boost::thread *thrd;
};

BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID
lpReserved)
{
     if(ul_reason_for_call == DLL_PROCESS_ATTACH)
        {
                DrDT drdt;
     }
     return TRUE;
}

-- 
Loïc

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk