Ошибки, баги, вопросы - страница 2540

 
Сергей Таболин:

Чего вы хотите?

чтобы в обсуждение багов и конструкций не лезли со своими комментами некомпетентные типа тебя, федосеева и т.д.

чтобы конструкции и механизмы взятые в MQL из С++ целиком и выглядящие так же как в С++ работали так же как в С++.

Сергей Таболин:

Чтобы MQL был полным аналогом С++ ?

это бред и ты это знаешь, но тебе ведь набросить надо.
Сергей Таболин:

И хватит уже ныть и пускать сопли пузырями по этому поводу. Я открыл для таких "обсуждений" отдельную тему.

ноешь как раз ты. про то как достали, про отдельный язык и про отдельную ветку.

открой для себя и сочувствующих отдельную ветку и ной там.

 
Как заставить терминал отпустить mqd-файл? Или еще лучше, если бы был штатный способ удаления из интерфейса?
 
Stanislav Korotky:
Как заставить терминал отпустить mqd-файл? Или еще лучше, если бы был штатный способ удаления из интерфейса?

Примерно догадываюсь, о чем вопрос. Лучше переформулировать.

 
По моему есть проблема с деинициализацией dll в Сервисах, помогите разобраться.
Проблема вот в чём. После нажатия команды "Остановить" в меню Сервиса, терминал почему то не ждёт завершения функции Fn(). 
Преждевременно пытается разорвать связь с dll, вешая терминал или полностью вылетает (закрывается).
Хотя в точке входа DllMain, флаг Detach в DLL_PROCESS_DETACH явно переводит флаг для завершения цикла while. 

Но while не успевает выйти из цикла, чтобы выполнить функции ниже, по дополнительному завершению всех остальных процессов.
И завершить саму функцию Fn().
Функция DestroyFunction(); выступает как проверочная в данном примере.

Содержание dll

#define EXP extern "C" __declspec(dllexport)

void DestroyFunction(void);
EXP void __stdcall Fn(int num);

bool Detach;

//---------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
        switch (ul_reason_for_call)
        {
                case DLL_PROCESS_ATTACH:
                        Detach = false;
                        break;
                case DLL_THREAD_ATTACH:
                        break;
                case DLL_THREAD_DETACH:
                        break;
                case DLL_PROCESS_DETACH:
                        Detach = true;
                        break;
        }
        return TRUE;
}

//---------------------------------------------------------------------
void DestroyFunction()
{
        MessageBoxW(NULL, L"Start DestroyFunction", L"OK", MB_OK);

        return;
}

//---------------------------------------------------------------------
EXP void __stdcall Fn(int num)
{
        int count = num;

        while (Detach == false)
        {
            //Имитация работы цикла
            count++;    

            if (count > 0)
                MessageBoxW(NULL, L"Start While iteration", L"OK", MB_OK);

            Sleep(10000);
        }       

 
        //После нажатия команды "Остановить" в меню Сервис, сюда уже не доходим, так как уже висим, или вылетел терминал.
        DestroyFunction();

        
        return;
}


Содержание программы Сервис.
Дополнительная задержка по флагу  _StopFlag   не помогает.

//+------------------------------------------------------------------+
//|                                                      BugDll.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property service
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property script_show_inputs


#import "BugDll.dll"
   void Fn(int num);
#import


//+------------------------------------------------------------------+
//| Service program start function                                   |
//+------------------------------------------------------------------+
int OnStart()
{      
   
   Fn(0);

   if(_StopFlag)
      Sleep(10000);
   
   return(0);
}
//+------------------------------------------------------------------+


 

Файлы:
MQL5.zip  54 kb
 
Roman:
По моему есть проблема с деинициализацией dll в Сервисах, помогите разобраться.

длл выгружается не (обязательно) сразу после завершения сервиса (могу ошибаться)

в любом случае то что вы делаете при DLL_PROCESS_DETACH это уже поздно. Сделайте явную функцию deinit в длл которая будет выставлять этот флаг и явно вызываться при завершении сервиса.

 
Roman: 

Терминал начнет выгружать либу после возвращения потока из старт(), думаю. А то как получается? Программа работает, и начать ей окружение ломать? Ерунда ведь. Запустите в либе отдельный поток, а  не гоняя в цикле поток скрипта, и вот его уже сможет нормально завершить.

 
Vict:

Терминал начнет выгружать либу после возвращения потока из старт(), думаю. А то как получается? Программа работает, и начать ей окружение ломать? Ерунда ведь. Запустите в либе отдельный поток, и вот его уже сможет нормально завершить.

В том то и дело, что  с потоками та же беда, и из за этого не могу корректно завершить другие процессы (потоки), у которых куча объектов которые нужно уничтожить.
По этому сделал простой пример, который выше чтобы проверить, и оказывается проблема совсем в другом.
Терминал не корректно работает с точкой выхода  DLL_PROCESS_DETACH

Попробую как предложил TheXpert, но то что терминал выгружает dll сразу, не  зависимо от DLL_PROCESS_DETACH, это наверно и есть ошибка терминала.

TheXpert:

длл выгружается не (обязательно) сразу после завершения сервиса (могу ошибаться)

в любом случае то что вы делаете при DLL_PROCESS_DETACH это уже поздно. Сделайте явную функцию deinit в длл которая будет выставлять этот флаг и явно вызываться при завершении сервиса.

Спасибо за подсказку, попробую так сделать.

 
Roman:

В том то и дело, что  с потоками та же беда, и из за этого не могу корректно завершить другие процессы (потоки), у которых куча объектов которые нужно уничтожить.
По этому сделал простой пример, который выше чтобы проверить, и оказывается проблема совсем в другом.
Терминал не корректно работает с точкой выхода  DLL_PROCESS_DETACH

Попробую как предложил TheXpert, но то что терминал выгружает dll сразу, не  зависимо от DLL_PROCESS_DETACH, это наверно и есть ошибка терминала.

Спасибо за подсказку, попробую так сделать.

А с чего Вы взяли, что dll живет в отдельном потоке? У Вас банальное аварийное завершение работы программы, не обработанное в условиях цикла.

А DllMain запускается при подключении/отключении dll к процессу DLL_PROCESS и при создании/прекращении работы потока, созданного в этом процессе DLL_THREAD. Так что Ваш bool Detach, не факт, что и вообще существует внутри dll, ибо компилятор мог его и убрать в рамках оптимизации, так как в процессе исполнения всех функций во время жизни dll он не меняется и равен false.

 
Vladimir Simakov:

А с чего Вы взяли, что dll живет в отдельном потоке? У Вас банальное аварийное завершение работы программы, не обработанное в условиях цикла.

А DllMain запускается при подключении/отключении dll к процессу DLL_PROCESS и при создании/прекращении работы потока, созданного в этом процессе DLL_THREAD. Так что Ваш bool Detach, не факт, что и вообще существует внутри dll, ибо компилятор мог его и убрать в рамках оптимизации, так как в процессе исполнения всех функций во время жизни dll он не меняется и равен false.

Не где не было сказано, что dll живёт в отдельном потоке.
Это мы с Vict общались, и друг друга поняли о чём речь ))
То что аварийное завершение это понятно, не понятно почему не срабатывает флаг в DLL_PROCESS_DETACH для выхода из цикла while.
А что касается DLL_THREAD, то они вообще не доступны для mql, об этом пишется в этой статье, проверял, действительно не работают.
А вот с компилятором VS как вариант, тоже может быть прикол.
Хотелось бы услышать пояснения компетентных представителей, а не гадать  ))  

 
Roman:
По моему есть проблема с деинициализацией dll в Сервисах, помогите разобраться.
Проблема вот в чём. После нажатия команды "Остановить" в меню Сервиса, терминал почему то не ждёт завершения функции Fn(). 
Преждевременно пытается разорвать связь с dll, вешая терминал или полностью вылетает (закрывается).
Хотя в точке входа DllMain, флаг Detach в DLL_PROCESS_DETACH явно переводит флаг для завершения цикла while. 

Но while не успевает выйти из цикла, чтобы выполнить функции ниже, по дополнительному завершению всех остальных процессов.
И завершить саму функцию Fn().
Функция DestroyFunction(); выступает как проверочная в данном примере.

Содержание dll


Содержание программы Сервис.
Дополнительная задержка по флагу  _StopFlag   не помогает.


 

Так вы же не вернули управление обратно в терминал, "зависли" в "бесконечном" цикле внутри Fn в DLL.
О каком нормальном завершении может идти речь!

Если нужно подобное поведение, то внутри Fn в DLL необходимо запустить отдельный поток с циклом, который останавливать по флагу, который выставляется в отдельной функции FnStop и при DLL_PROCESS_DETACH
Причина обращения: