Search code examples
c++dllsegmentation-faultboost-threadfreeze

Crash when using boost::timed_join and FreeLibrary


I require the use of LoadLibrary and GetProcAddress to call functions from some dlls (which plug into my app), but I don't want them to be able to hang my program by containing an infinite loop or hanging themselves, so I'm trying to use boost::thread (no experience) to circumvent that. However, if a function does hang, I crash with ACCESS_DENIED (0x00000005) when calling FreeLibrary to clean up.

Here's a minimal DLL (mydll.dll) that reproduces the problem:

extern "C" {
    void __declspec(dllexport) foo() {
        for(;;); //<-- infinite loop
    }
}

And here's a minimal cpp that crashes. I've left out error checking for brevity, but I can assure you no errors are given:

#include <boost/thread.hpp>
#include <iostream>
#include <windows.h>

int main() {
    using FuncType = void (*)();

    HMODULE dll = LoadLibrary("mydll.dll");

    FuncType func = (FuncType)GetProcAddress(dll, "foo");

    boost::thread thr = [func] {func();};

    if (!thr.timed_join(boost::posix_time::seconds(1))) {
        std::cout << "Timed out.";
        //thr.detach();
        FreeLibrary(dll);
    }

    for (;;);
}

Upon running this, "Timed out." is printed and the call stack (gdb on CodeBlocks) at the crash is as follows:

#0 00000000 0x6c1c1214 in ??() (??:??)
#1 0040133E operator() (__closure=<optimized out>) (C:\...\thread test.cpp:17)
#5 00000000 0x00000000 in ??() (??:??)

Without optimizations, that becomes:

#0 00000000 0x6c1c1214 in ??() (??:??)
#1 00401348 operator() (__closure=0x898f90) (C:\...\thread test.cpp:17)
#2 00401780 boost::detail::thread_data<main()::<lambda()> >::run(void)(this=0x898f70) (c:/.../boost/thread/detail/thread.hpp:62)
#5 00000000 0x00000000 in ??() (??:??)

The first thing I tried was adding in the thr.detach(); line that I commented out above, but that produced the same result.

I've also tried the following to no avail:

  • Replacing the lambda with a function (I'm not sure how well Boost fits in with C++11 stuff) --- crashes
  • Commenting out the FreeLibrary line --- works fine, but I'd rather free it after loading it, even if it is reference-based. I'm also cautious about that kind of behaviour working later on.
  • Replacing the infinite loop in the DLL with one that returns --- works fine, but I can't count on that
  • Not using LoadLibrary or anything and inlining the infinite loop --- works fine, but I need to use DLLs:

boost::thread thr = []{for (;;);};

The DLL and cpp were both compiled on Windows 7 64-bit using GCC 4.7.1 with 32-bit output types. My version of Boost is 1.49.0. If memory serves, I think I got one or two tests in on Windows XP 32-bit (same compiler etc) before moving to a different computer as well.

Why is this crashing? How can I ensure a function I call dynamically doesn't hang my program?


Solution

  • Fundamentally, you can't do that. Threads don't provide that kind of isolation. Use processes if you need that.