mercredi 1 mars 2017

Worker threads are forcibly terminated prior to the destruction of static objects in a DLL (but not .exe)?

Consider the following code. All of the following was compiled and executed in Visual Studio 2015 using the v140 C++ runtime:

#include <thread>
#include <atomic>
#include <sstream>

#include <Windows.h>

struct StaticThreadTest
{
    ~StaticThreadTest()
    {
        _terminationRequested = true;
        if (_thread.joinable())
            _thread.join();

        std::ostringstream ss;
        ss << "Thread finished gracefully: " << _threadFinishedGracefully << "\n";
        OutputDebugStringA(ss.str().c_str());
    }

    void startThread()
    {
        _thread = std::thread([&]() {
            while (!_terminationRequested);

            _threadFinishedGracefully = true;
        });
    }

    std::thread _thread;
    std::atomic<bool> _terminationRequested {false};
    std::atomic<bool> _threadFinishedGracefully {false};
};

static StaticThreadTest thread;

int main()
{
    thread.startThread();

    return 0;
} 

It works just as expected - "Thread finished gracefully: 1" is printed and the application exits.

However, if I move this code to a DLL (create an empty DLL, export one function from it, place the StaticThreadTest object in the dll's .cpp, call thread.startThread() from the exported function and call this exported function from main.cpp), the code sometimes prints "Thread finished gracefully: 0", but more often than not it just hangs in thread.join().

Is this behavior documented? Is it a bug in the runtime or is this intended?

Of note: the same code but compiled with the v120 toolset hangs 100% of the time even in main.cpp (in the exe). Seems as if there was a bug in the v120 toolset, and in v140 it is fixed for .exe but not for .dll.

Aucun commentaire:

Enregistrer un commentaire