Сбой при использовании boost :: timed_join и FreeLibrary

Я требую использования LoadLibrary а также GetProcAddress вызывать функции из некоторых библиотек (которые подключаются к моему приложению), но я не хочу, чтобы они могли повесить мою программу, заключив в себе бесконечный цикл или повесив себя, поэтому я пытаюсь использовать boost::thread (нет опыта), чтобы обойти это. Тем не менее, если функция зависает, я вызываю сбой с ACCESS_DENIED (0x00000005) при вызове FreeLibrary очистить.

Вот минимальная DLL (mydll.dll) что воспроизводит проблему:

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

И вот минимальный cpp, который вылетает. Я упустил проверку ошибок для краткости, но я могу заверить вас, что никаких ошибок не дано:

#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 (;;);
}

После запуска этого, «Тайм-аут». печатается и стек вызовов (gdb на CodeBlocks) при сбое выглядит следующим образом:

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

Без оптимизации это становится:

#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 ??() (??:??)

Первое, что я попробовал, было добавить в thr.detach(); Строка, которую я прокомментировал выше, но которая дала тот же результат.

Я также попробовал следующее безрезультатно:

  • Замена лямбда-функции (я не уверен, насколько хорошо Boost подходит для C ++ 11) — вылетает
  • Комментируя FreeLibrary line — работает нормально, но я бы предпочел освободить его после загрузки, даже если он основан на ссылках. Я также осторожен с таким поведением, которое будет работать позже.
  • Замена бесконечного цикла в DLL на возвращающий — работает нормально, но я не могу на это рассчитывать
  • Не используется LoadLibrary или что-нибудь и встраивание бесконечного цикла — работает нормально, но мне нужно использовать DLL:

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

DLL и cpp были скомпилированы в 64-битной Windows 7 с использованием GCC 4.7.1 с 32-битными типами вывода. Моя версия Boost 1.49.0. Если память работает, я думаю, что я получил один или два теста на 32-битной Windows XP (тот же компилятор и т. Д.), Прежде чем перейти на другой компьютер.

Почему это сбой? Как я могу гарантировать, что функция, которую я вызываю динамически, не вешает мою программу?

1

Решение

По сути, вы не можете этого сделать. Потоки не обеспечивают такую ​​изоляцию. Используйте процессы, если вам это нужно.

2

Другие решения

Других решений пока нет …