Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > завершение потока в dllmain


Автор: Lazin 16.10.2007, 14:53
Ситуация такая:
dll-ка создает объект, объект, в свою очередь, запускает поток. Для завершения потока используется event, который устанавливается в деструкторе объекта. Но, как выяснилось, когда деструктор начинает выполняться - поток уже не работает.

Код

class CActiveObj
{
HANDLE event;
  public:
  CActiveObj()
  {
    //здесь создается поток
  }

  ~CActiveObj
  {
    ::SetEvent(event);
    //ждем завершения потока
  }

   ********

  unsigned int ThreadExec(void*)
  {
    while(true)
    {
        HANDLE events[] = {event, ....};
        DWORD r = ::WaitForMultipleObjects(EVENTS_COUNT, events,  FALSE, INFINITE);
        if (r == WAIT_OBJECT_0) {::_endthread();}
        else *****
    }
  }
};

dllmain.cpp
Код

CActiveObj * obj = NULL;

BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
    switch ( dwReason )
    {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls( hinstDLL );
            obj = new CActiveObj();
        break;

        case DLL_PROCESS_DETACH: 
            delete obj;
        break;
    }
    return TRUE;
}

По идее при выполнении DLL_PROCESS_DETACH объект должен быть удален и поток остановлен, но этого не происходит, так как поток в момент выполнения delete obj; уже мертв.
Как правильно дождаться завершения потока в dllMain, и возможно-ли это.

Автор: Nastya 16.10.2007, 15:06
Запоминай HANDLE потока и жди его WaitForSingleObject 

Автор: Lazin 16.10.2007, 15:26
Цитата(Nastya @  16.10.2007,  15:06 Найти цитируемый пост)
Запоминай HANDLE потока и жди его WaitForSingleObject  

Я так и делаю,
Код

  ~CActiveObj
  {
    ::SetEvent(event);
    //ждем завершения потока
  }

на самом деле вместо комментария там ф-я WaitForSingleObject, которой в качестве аргумента передается хэндл потока. Дело в том что когда управление доходит до этого места поток уже завершен. 
Кстати забыл написать, что без dll код работает нормально (если подключить мой исходник к проекту). Но проблема в том что нужно именно в качестве длл. Мне кажется это связано с тем, что код который выполняется в потоке физически находится в dll, поэтому система и убивает его при выгрузке длл-ки, но точно я не знаю. 


Автор: SergeCpp 16.10.2007, 23:45
Всего кода не вижу, но Вам стоило бы вот так примерно подстраховаться против выгрузки DLL

Код
            // load once more to prevent from unloading when hook removed
            // also set handle

            g_hClockDLL = LoadLibrary( g_pClockDLLName );

            DWORD tid; // Win9x requirement for CreateThread()

            CloseHandle( CreateThread( NULL,
                                       0x2000,    // initial commit stack size
                                       ( PTHREAD_START_ROUTINE )ClockMain,
                                       NULL,    // some parameter can be passed if needed
                                       0,
                                       &tid ) );
//... файл Clock.cpp


(http://sergecpp.mylivepage.ru/file/1/2/ нечто аналогичное Вашему с потоками делается)

Автор: Lazin 17.10.2007, 09:20
Цитата(SergeCpp @  16.10.2007,  23:45 Найти цитируемый пост)
(там нечто аналогичное Вашему с потоками делается)

спасибо за исходник, но там немного не то происходит, что мне нужно.
Ситуация такая:
Есть множество программ, использующих мою библиотеку(статичесски). Когда одна из программ загружает dll, мой код создает поток. При выгрузке библиотеки, нужно дождаться завершения потока, который должен выполнить определенную работу. Так вот, когда в ф-и DllMain выполняется
Код


case DLL_PROCESS_DETACH: 
            delete obj;
break;

поток завершается, но не нормальным образом - как при TerminateThread.
Возможности изменить клиентский код у меня нет.

Автор: SergeCpp 17.10.2007, 11:30
Проверьте точку входа DLL (если явно не ставили в опциях, то MSVC вызовет сначала свою)

Я бы не использовал всякие надстройки типа ::_endthread();

И перечитайте внимательнее Рихтера и MSDN по данному вопросу

В качестве проверок поставьте точки прерывания в ключевых местах

Удачи Вам! Тут несложно, только делать нужно самому, согласны?

Автор: Lazin 17.10.2007, 13:14
SergeCpp, Ok

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)