Правильная вигрузка dll

Тема в разделе "WASM.BEGINNERS", создана пользователем 984259h, 30 мар 2010.

  1. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    есть длл на DLL_PROCESS_ATTACH создается поток в этом потоке бесконечный цикл

    DWORD WINAPI BackConnectLoop(LPVOID lpParam)
    {
    //инициализация сокетов бла бла
    for(;;)
    {

    connect(....)


    sleep(800);
    }

    return 0
    }
    и собственно на DLL_PROCESS_ATTACH

    DWORD dwIDMainConn;
    HANDLE hThreadMainConn = CreateThread(NULL,0,&BackConnectLoop,NULL,0,&dwIDMainConn);

    но как правильно сделать на DLL_PROCESS_DETACH

    делал так

    DWORD ExitCode(0);
    GetExitCodeThread(hThreadMainConn,&ExitCode);
    TerminateThread(hThreadMainConn,0);
    WaitForSingleObject(hThreadMainConn,INFINITE);

    пожно как то поток уведомить на выгрузку длл
     
  2. PowerASM

    PowerASM New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    59
    ну а event создать или просто переменную, которую периодически проверять в этом самом потоке.
     
  3. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    делал вот так еще

    bool bCheck;

    DWORD WINAPI BackConnectLoop(LPVOID lpParam)
    {
    //инициализация сокетов бла бла
    while(bCheck == true)
    {

    connect(....)


    sleep(800);
    }

    ExitThread(0); /// доходит сюда и висит
    return 0
    }

    DLL_PROCESS_ATTACH

    bCheck = true;
    DWORD dwIDMainConn;
    HANDLE hThreadMainConn = CreateThread(NULL,0,&BackConnectLoop,NULL,0,&dwIDMainConn);


    DLL_PROCESS_DETACH

    bCheck = false;
    WaitForSingleObject(hThreadMainConn,INFINITE);


    в потоке ExitThread(0); висит почему ? не пойму естественно WaitForSingleObject ожидаем до безкочечности
     
  4. PowerASM

    PowerASM New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    59
    Вы можете просто оставить return 0. ExitThread нужен для не предвиденного выхода из потока, но в конце функции это не обязательно.
    И что значит висит. может она просто из нее не возвращается, как и в случае с ExitProcess.
     
  5. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    работает только когда вмнесто ExitThread(0) сделать вот так
    DWORD dwExitCode;
    GetExitCodeThread(GetCurrentThread(),&dwExitCode);
    TerminateThread(GetCurrentThread(),dwExitCode);
     
  6. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    висит имелось ввиду когда пошагово дохожу до ExitThread(0) cpp отладчиком то вызывается ExitThread(0) и все
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Завершать потоки при захваченной LdrpLoaderLock весьма плохое решение. Ядро помогает освобождая кс, но это может закончится общей рассинхронизацией, например зависанием иного потока обратившегося к загрузчику.
     
  8. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    Как правильно тогда завершить поток на DLL_PROCESS_DETACH
     
  9. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    А вообще есть этому решению альтернатива ?
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    я делал так... один поток в цикле принимал оконные сообщения:
    if(IsGUIThread(TRUE) == FALSE) { return 1; } // Важный момент
    ...
    while(m_bWorking) // Цикл обработки команд из вне
    {
    GetMessage(&msg, NULL, 0, 0);
    switch(msg.message)
    {
    ...
    case CTRLMES_EXIT: // Команда на завершение работы DLL
    m_bWorking = false;
    break;
    ...
    }
    }
    ...
    // Освобождение ресурсов потока
    return 0; // Выход потока
    другой работал со своими задачами:
    while(m_bWorking)
    {
    ....
    }
    // Освобождение ресурсов потока
    return 0; // Выход потока
    управляющие сообщения посылались из другого процесса с помощью PostThreadMessage, m_bWorking - глобальная булевая переменная, инициализированная true... ещё важно заботиться об использованных ресурсах... очищать память и закрывать хендлы, так как они ассоциируются с процессом, а не с потоком... забивание на них в итоге может привести к некорректному завершению процесса или например к блокировке доступа к файлу... вообще если о памяти говорить, то лучше использовать кучи, а если говорить о потоках, то лучше использовать _beginthread... ты спросишь "почему?" - читай ответ у Рихтера))))
     
  11. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    ай... забыл поставить тег для кода... извиняйте!
     
  12. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    to Rel Насколько я понял в данном случае При вызове LoadLibrary будет крутится цикл в текущем потоке то есть приложение которое вызывает LoadLibrary на ней остановится и будет ожидать остановки цикла только тогда можно выполнять какой нить код мне нужно что бы не было "остановки" на LoadLibrary
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    в DllMain не логично делать никаких циклов... в данном случае в DllMain создаются два потока: рабочий и обработки сообщений... чтобы прервать работу dll достаточно послать сообщение о выгрузке потоку обработчику сообщений, подождать завершения потоков и вызвать FreeLibrary... плюс ещё в том, что подобные вещи удобно делать из другого процесса...
     
  14. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    to Rel "подождать завершения потоков и вызвать FreeLibrary" а если поток бесконечный то есть цикл while(1) а тут надо выгрузить длл тогда как лучше сделать ?
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    ты вообще читал, что я выше написал тебе? уже второй дурацкий вопрос... не надо делать бесконечных циклов, циклы должны быть управляемые...
    как только цикл обработки сообщений принял сообщение на выход, то:
    оба потока выйдут из циклов и корректно завершатся... после чего можешь освобождать память либо вручную, либо c помощью FreeLibrary...
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Rel
    Достаточно одного цикла и одного потока. Совместить рабочий цикл с циклом выборки сообщений за счёт PeekMessage. Соответственно никаких разделяемых переменных в случае управления сообщениями не нужно.
    После отправки сообщения (или альтернативно — установки переменной-переключателя) из DLL_PROCESS_DETACH ожидать на хэндле потока, который был сохранён при создании потока из DLL_PROCESS_ATTACH.
     
  17. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    да... согласен... на детаче можно эту переменную переключить, тогда вообще не обязательно обрабатывать сообщения, и следовательно не нужно делать гуевым поток-обработчик сообщений... просто предложенный мною метод дает некую гибкость управления dll извне процесса...
     
  18. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    to Rel
    Объясните пожалуйста вот это
    Код (Text):
    1. HANDLE hShutdownEvent = NULL;
    2. HANDLE hThreadMainConn = NULL;
    3.  
    4. DWORD WINAPI Thread_func(LPVOID param)
    5. {
    6.   DWORD  nEvent;
    7.   while(1)
    8.   {
    9.     nEvent = WaitForMultipleObjects(1,&hShutdownEvent,FALSE,100);
    10.     if(nEvent == 0)
    11.     {
    12.      
    13.       break;
    14.     }
    15.     //....... code
    16.   }
    17.  ExitThread(0);
    18. return 0;
    19. }
    20.  
    21. int __stdcall DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
    22. {
    23.  switch (ul_reason_for_call)
    24.  {
    25.   case DLL_PROCESS_ATTACH:
    26.   {
    27.     DWORD dwIDMainConn;
    28.     hShutdownEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
    29.     hThreadMainConn = CreateThread(NULL,0,&Thread_func,NULL,0,&dwIDMainConn);
    30.    break;
    31.   }
    32.   case DLL_PROCESS_DETACH:
    33.   {
    34.     SetEvent(hShutdownEvent);
    35.     CloseHandle(hShutdownEvent);
    36.     CloseHandle(hThreadMainConn);
    37.     break;  
    38.   }
    39.  }
    40.  return 0x01;
    41. }
    и вызов с екзе
    Код (Text):
    1.   HMODULE hModule = LoadLibraryA("MyDll.dll");
    2.   Sleep(10*1000);
    3.   FreeLibrary(hModule);
    после FreeLibrary(hModule); если (в отладчике ) ошибка если просто запускаю екзе после FreeLibrary(hModule); екзе работает несколько минут после чего завершается
     
  19. PowerASM

    PowerASM New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    59
    984259h
    Странно, а должен 10 секунд
    А какой отладчик. Возможно надо еще либо подождать (поставить Sleep между Set и Close, либо SwitchToThread), либо создать цикл ожидания обработки установленного Event т.к. под отладчиком может не произойти переключения потоков, особенно в пошаговом режиме
     
  20. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    PowerASM
    обычный с - шный