Тест зависания терминала QUIK 10.0.1.18

Страницы: 1
RSS
Тест зависания терминала QUIK 10.0.1.18
 
Берём следующий скрипт. Если в первой строке стоит flag = true, то скрипт нормально запускается и останавливается из меню скриптов. Если в первой строке поставить flag = false, происходит зависание терминала при остановке скрипта. В зависимости от значения переменной flag либо имеется sleep(0) в функции main(), либо отсутствует на пути выполнения кода.

У меня зависание воспроизводится в терминалах версий 10.0.0 и 10.0.1.

Три вопроса:
1) Может ли кто-то ещё подтвердить, что зависание происходит (чтобы исключить особенность моего компьютера)?
2) Знает ли кто-то причину такого поведения?
3) Что разработчики терминала могут сказать по этому поводу?

Сам скрипт:

Код
local flag = true -- если установить в false, то при остановке скрипта происходит зависание (убирается sleep(0) в функции main)

local foregroundColor = RGB(0, 0, 0)
local backgroundColor = RGB(192, 255, 192)

local interrupted = false
local tableId

local function setTableColors(foregroundColor, backgroundColor)
    local nRows, nCols = GetTableSize(tableId)
    if nRows and nCols then
        for row = 1, nRows do
            for col = 1, nCols do
                SetColor(tableId, row, col,
                        backgroundColor, foregroundColor,
                        backgroundColor, foregroundColor)
            end
        end
    end
end

local function ensureWindowOpened()
    if tableId == nil then
        return
    end
    if IsWindowClosed(tableId) then
        CreateWindow(tableId)
        SetWindowPos(tableId, 0, 0, 300, 100)
        SetWindowCaption(tableId, "hang_test")
        InsertRow(tableId, 1)
        InsertRow(tableId, 2)
        SetCell(tableId, 1, 1, "11")
        SetCell(tableId, 1, 2, "12")
        SetCell(tableId, 2, 1, "21")
        SetCell(tableId, 2, 2, "22")
        SetSelectedRow(tableId, 1)
    end
    setTableColors(foregroundColor, backgroundColor)
end

local function closeWindow()
    local t = tableId
    tableId = nil
    if t then
        DestroyTable(t)
    end
end

function OnInit(scriptPath)
    tableId = AllocTable()
    AddColumn(tableId, 1, "col1", true, QTABLE_STRING_TYPE, 5)
    AddColumn(tableId, 2, "col2", true, QTABLE_STRING_TYPE, 5)
    SetTableNotificationCallback(tableId, function(tId, msg, par1, _)
        if msg == QTABLE_SELCHANGED then
            SetSelectedRow(tId, 1)
        end
    end)
    ensureWindowOpened()
end

local function run()
    ensureWindowOpened()
    if tableId then
        SetSelectedRow(tableId, 2)
    end
end

function OnStop(flag)
    pcall(closeWindow)
    interrupted = true
end

function main()
    message("STARTED", 1)
    while not interrupted do
        run()
        if flag then
            sleep(0)
        end
    end
    pcall(closeWindow)
    message("SHUTDOWN", 1)
end

 
Цитата
_sk_ написал:
2) Знает ли кто-то причину такого поведения?
  Проверил у себя в песочнице 10.1.  Ваш скрипт зависает при flag = false.
 Как известно, длинный участок фрагмента кода скрипта на "чистом Lua" в main (без вызова C-функций) блокирует выполнение потока обслуживающего колбеки.
Функция sleep(0) - это C-функция.  Когда вы исключаете ее исполнение (в цикле), то получается бесконечный фрагмент скрипта на "чистом Lua" и OnStop, являющийся колбеком не может быть выполненным.
 
Спасибо. Я также проверял в терминале версии 9.7, там не было зависания почему-то.
 
Цитата
TGB написал:
Цитата
_sk_ написал:
2) Знает ли кто-то причину такого поведения?
   Проверил у себя в песочнице 10.1.  Ваш скрипт зависает при flag = false.
 Как известно, длинный участок фрагмента кода скрипта на "чистом Lua" в main (без вызова C-функций) блокирует выполнение потока обслуживающего колбеки.
Функция sleep(0) - это C-функция.  Когда вы исключаете ее исполнение (в цикле), то получается бесконечный фрагмент скрипта на "чистом Lua" и OnStop, являющийся колбеком не может быть выполненным.
Тут с OnStop какая-то проблема, как мне кажется.

Заменяем фрагмент с кодом OnStop() вот на такое:

Код
function OnAllTrade(t)
    message("OnAllTrade", 1)
end

function OnStop(flag)
    message("OnStop executed", 1)
    pcall(closeWindow)
    interrupted = true
end
Проверяем ещё раз и видим, что:
1) коллбэки OnAllTrade выполняются (есть такие сообщения, если терминал получает обезличенные сделки);
2) при остановке скрипта терминал зависает, но при этом видно последнее сообщение "OnStopExecuted".

В принципе, вместо OnAllTrade можно любой другой коллбэк поставить (OnQuote, OnParam).
 
Цитата
_sk_ написал:
Тут с OnStop какая-то проблема, как мне кажется.
  Причину я описал в своем комментарии.
В вашем скрипте эта причина проявляется следующим образом.
В цикле функции main есть два фрагмента кода с вызовами C-функций. Это sleep(0) и косвенно вызываемые (с помощью  функции run()) стандартные функции работы с таблицами QUIK.  При отключении sleep(0) остаются C-функции работы с таблицами QUIK. Поэтому OnStop запускается в потоке обработки колбеков (с выдачей сообщения "OnStop executed"). Но далее запускается pcall(closeWindow).  В функции closeWindow отключается фрагмент работы с таблицами QUIK. Исполняемый код цикла функции main при этом представляет код на "чистом Lua".  Внутри исполнения pcall(closeWindow) существует вызов C-функции (я с этим уже разбираться не буду), при котором блокируется поток обработки колбеков, но отпускается поток main, где в цикле выполнения кода на "чистом Lua" блокируется поток выполняемый функцию OnStop. QUIK виснет.
 
Цитата
_sk_ написал:
Я также проверял в терминале версии 9.7, там не было зависания почему-то.
  Я проверил у себя в версии 9.7.0.14.  Зависание есть.
 
Цитата
TGB написал:
Цитата
_sk_ написал:
Тут с OnStop какая-то проблема, как мне кажется.
   Причину я описал в своем комментарии.
В вашем скрипте эта причина проявляется следующим образом.
В цикле функции main есть два фрагмента кода с вызовами C-функций. Это sleep(0) и косвенно вызываемые (с помощью  функции run()) стандартные функции работы с таблицами QUIK.  При отключении sleep(0) остаются C-функции работы с таблицами QUIK. Поэтому OnStop запускается в потоке обработки колбеков (с выдачей сообщения "OnStop executed"). Но далее запускается pcall(closeWindow).  В функции closeWindow отключается фрагмент работы с таблицами QUIK. Исполняемый код цикла функции main при этом представляет код на "чистом Lua".  Внутри исполнения pcall(closeWindow) существует вызов C-функции (я с этим уже разбираться не буду), при котором блокируется поток обработки колбеков, но отпускается поток main, где в цикле выполнения кода на "чистом Lua" блокируется поток выполняемый функцию OnStop. QUIK виснет.
Спасибо большое за пояснение!
 
Цитата
3) Что разработчики терминала могут сказать по этому поводу?

Осталось услышать комментарии от разработчиков / техподдержки.
 
Цитата
_sk_ написал:
Спасибо большое за пояснение!
   Если код функции OnStop модифицировать следующим образом:
Код
function OnStop(flag)
    interrupted = true
    message("OnStop executed", 1)
    pcall(closeWindow)
end

  то зависания не будет и, наверное, понятно почему.
 
Цитата
_sk_ написал:
Берём следующий скрипт. Если в первой строке стоит flag = true, то скрипт нормально запускается и останавливается из меню скриптов. Если в первой строке поставить flag = false, происходит зависание терминала при остановке скрипта. В зависимости от значения переменной flag либо имеется sleep(0) в функции main(), либо отсутствует на пути выполнения кода.

У меня зависание воспроизводится в терминалах версий 10.0.0 и 10.0.1.

Три вопроса:
1) Может ли кто-то ещё подтвердить, что зависание происходит (чтобы исключить особенность моего компьютера)?
2) Знает ли кто-то причину такого поведения?
3) Что разработчики терминала могут сказать по этому поводу?

Сам скрипт:

Код
   local  flag  =   true   -- если установить в false, то при остановке скрипта происходит зависание (убирается sleep(0) в функции main) 

 local  foregroundColor  =   RGB ( 0 ,  0 ,  0 )
 local  backgroundColor  =   RGB ( 192 ,  255 ,  192 )

 local  interrupted  =   false 
 local  tableId

 local   function   setTableColors (foregroundColor, backgroundColor)
     local  nRows, nCols  =  GetTable Size (tableId)
     if  nRows  and  nCols  then 
         for  row  =   1 , nRows  do 
             for  col  =   1 , nCols  do 
                 SetColor (tableId, row, col,
                        backgroundColor, foregroundColor,
                        backgroundColor, foregroundColor)
             end 
         end 
     end 
 end 

 local   function   ensureWindowOpened ()
     if  tableId  =  =   nil   then 
         return 
     end 
     if   IsWindowClosed (tableId)  then 
         CreateWindow (tableId)
         SetWindowPos (tableId,  0 ,  0 ,  300 ,  100 )
         SetWindowCaption (tableId,  "hang_test" )
         InsertRow (tableId,  1 )
         InsertRow (tableId,  2 )
         SetCell (tableId,  1 ,  1 ,  "11" )
         SetCell (tableId,  1 ,  2 ,  "12" )
         SetCell (tableId,  2 ,  1 ,  "21" )
         SetCell (tableId,  2 ,  2 ,  "22" )
         SetSelectedRow (tableId,  1 )
     end 
    setTableColors(foregroundColor, backgroundColor)
 end 

 local   function   closeWindow ()
     local  t  =  tableId
    tableId  =   nil 
     if  t  then 
         DestroyTable (t)
     end 
 end 

 function   OnInit (scriptPath)
    tableId  =   AllocTable ()
     AddColumn (tableId,  1 ,  "col1" ,  true , QTABLE_STRING_TYPE,  5 )
     AddColumn (tableId,  2 ,  "col2" ,  true , QTABLE_STRING_TYPE,  5 )
     SetTableNotificationCallback (tableId,  function (tId, msg, par1, _)
         if  msg  =  =  QTABLE_SELCHANGED  then 
             SetSelectedRow (tId,  1 )
         end 
     end )
    ensureWindowOpened()
 end 

 local   function   run ()
    ensureWindowOpened()
     if  tableId  then 
         SetSelectedRow (tableId,  2 )
     end 
 end 

 function   OnStop (flag)
    pcall(closeWindow)
    interrupted  =   true 
 end 

 function   main ()
     message ( "STARTED" ,  1 )
     while   not  interrupted  do 
        run()
         if  flag  then 
             sleep ( 0 )
         end 
     end 
    pcall(closeWindow)
     message ( "SHUTDOWN" ,  1 )
 end 

  
причина зависания вероятнее всего в том,
что функция main будет исполнена один раз до загрузки всех необходимых для корректной работы данных.
Предположу, что это ошибка автора  скрипта, так как в нем не учитывается многопоточность.  
 
чтобы устранить проблему надо разрешать работу колбекам ,
когда функция main получит все данные для ее нормальной работы.
иначе будет кир-дык.
 
Цитата
nikolz написал:
Предположу, что это ошибка автора  скрипта, так как в нем не учитывается многопоточность.  
  Филосов  :smile: .   Укажите конкретно в чем ошибка автора.
---
  Ошибки автора нет. Есть ошибка в QUIK, состоящая в том, что длинные участки фрагментов кода скрипта на "чистом Lua" (без вызова C-функций) блокируют переключение потоков обслуживающего колбеки и выполняющего main. Я не буду повторять свои комментарии по этому поводу. Читайте форум.
 
Цитата
TGB написал:
Цитата
_sk_ написал:
Спасибо большое за пояснение!
    Если код функции OnStop модифицировать следующим образом:
Код
   function   OnStop (flag)
    interrupted  =   true 
     message ( "OnStop executed" ,  1 )
    pcall(closeWindow)
 end 
  

  то зависания не будет и, наверное, понятно почему.
Да, так и есть. Я пробовал этот вариант, но уже не стал писать в теме.

В общем, получается, что неплохо бы со стороны разработчиков обеспечить переключение между потоками даже в случае "длинного чистого Lua-кода". Я видел Ваши предложения по этому поводу, на которые разработчики, к сожалению, не реагируют.

Конечно, большинство программ пользователей имеют главный цикл со sleep внутри, так что совсем уж в явном виде проблема не стоит. Но переключение между потоками может сделать как работу терминала более отзывчивой, а также зависание, с которым я столкнулся, исключит.
 
Цитата
TGB написал:
Цитата
nikolz написал:
Предположу, что это ошибка автора  скрипта, так как в нем не учитывается многопоточность.  
   Филосов  :: .   Укажите конкретно в чем ошибка автора.
---
  Ошибки автора нет. Есть ошибка в QUIK, состоящая в том, что длинные участки фрагментов кода скрипта на "чистом Lua" (без вызова C-функций) блокируют переключение потоков обслуживающего колбеки и выполняющего main. Я не буду повторять свои комментарии по этому поводу. Читайте форум.
ошибка автора в отсутствии знаний.
И Ваша тоже так как Вы пишите про "чистый луа" который существует лишь в виде функций на чистом СИ.
Это профанация и дилетанты вам верят.
 
читайте внимательно документацию прежде чем писать тесты.
----------------
Например,
OnStop - Функция вызывается терминалом QUIK при остановке скрипта из диалога  управления и при закрытии терминала QUIK.

Функция возвращает количество миллисекунд, которое дается скрипту на  завершение работы.

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

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

=======================

Т е Вам дали время на завершение потока майн

Там и надо закрывать окна. А Вы делаете это в колбеке.

Вы это где прочитали?

 
зачем закрывать окно и в колбеке и в main?
----------------------------
function OnStop(flag)
  pcall(closeWindow)
   interrupted = true
end

function main()
   message("STARTED", 1)
   while not interrupted do
       run()
       if flag then
           sleep(0)
       end
   end
  pcall(closeWindow)
   message("SHUTDOWN", 1)
end
====================
 
в колбеке
в этой функции Вы уничтожаете окно
----------------------------
local function closeWindow()
   local t = tableId
   tableId = nil
   if t then
       DestroyTable(t)
   end
end
------------------
А в main вы уничтожаете nil.
Очевидно у Вас все вылетает по ошибке
и вы вместо того чтобы правильно сделать ставите pcall
----------------
Т е не зная причину Вы блокируете сообщение об ошибке.
полный дилетантизм.
 
"Чистый луа" к пустой голове прикладывать бесполезно.
 
Цитата
_sk_ написал:
Я видел Ваши предложения по этому поводу, на которые разработчики, к сожалению, не реагируют.
   Для QLua 5.3 есть простое и эффективное решение, которое я протестировал. Но это решение не подходит к Qlua 5.4 так как там было существенно изменено управление памятью и с этим я разбираться не стал. Разработчик QUIK (через поддержку) заявил, что будет поддерживаться только QLua 5.4. Поэтому свои предложения я снял, опасаясь того, что  их реализация разработчиком в QLua 5.4. может оказаться некорректной и последствия могут оказаться более неприятными чем то, что есть сейчас.
 
исправьте ошибку в скрипте и сделайте так:
Код
function main()
    message("STARTED", 1)
    while not interrupted do
        run()
       sleep(10)
    end
    pcall(closeWindow)
    message("SHUTDOWN", 1)
end
и читайте больше учебники а не треп на форуме.
 
_sk_,
вот Ваш тест с исправленными Вашими ошибками.
Работает без проблем.

Код
local flag =false -- можно и false и true

local foregroundColor = RGB(0, 0, 0)
local backgroundColor = RGB(192, 255, 192)

local function setTableColors(foregroundColor, backgroundColor)
    local nRows, nCols = GetTableSize(tableId)
    if nRows and nCols then
        for row = 1, nRows do
            for col = 1, nCols do
                SetColor(tableId, row, col,
                        backgroundColor, foregroundColor,
                        backgroundColor, foregroundColor)
            end
        end
    end
end

local function ensureWindowOpened()
    if tableId == nil then     return   end
    if IsWindowClosed(tableId) then
        CreateWindow(tableId)
        SetWindowPos(tableId, 0, 0, 300, 100)
        SetWindowCaption(tableId, "hang_test")
        InsertRow(tableId, 1)
        InsertRow(tableId, 2)
        SetCell(tableId, 1, 1, "11")
        SetCell(tableId, 1, 2, "12")
        SetCell(tableId, 2, 1, "21")
        SetCell(tableId, 2, 2, "22")
        SetSelectedRow(tableId, 1)
    end
    setTableColors(foregroundColor, backgroundColor)
end

function OnInit(scriptPath)
    tableId = AllocTable()
    AddColumn(tableId, 1, "col1", true, QTABLE_STRING_TYPE, 5)
    AddColumn(tableId, 2, "col2", true, QTABLE_STRING_TYPE, 5)
    SetTableNotificationCallback(tableId, function(tId, msg, par1, _)
        if msg == QTABLE_SELCHANGED then
            SetSelectedRow(tId, 1)
        end
    end)
    ensureWindowOpened()
end

local function run()
    ensureWindowOpened()
    if tableId then
        SetSelectedRow(tableId, 2)
    end

end

function OnStop(flag)
   DestroyTable(tableId);
    interrupted = true
end

function main()
    message("STARTED", 1)
    while not interrupted do
        run()
       if flag then
            sleep(0)
        end
    end
    message("SHUTDOWN", 1)
end

 
 
Цитата
nikolz написал:
_sk_ ,вот Ваш тест с исправленными Вашими ошибками. Работает без проблем.
   Вы до сих пор не поняли, что у _sk_ нет проблем со скритом ( он делает flag  =   true и все у него хорошо ). Его интерисует странное поведение скрипта когда flag =false и это нормально.
  Вообще, из того что видно невооруженным взглядом, у вас постоянный зуд отметиться на форуме (как у собачки, выпущенной на прогулку  :smile: ). Зачем вы работаете на форуме «прокладкой» между комментариями?
  Явно, что у вас проблемы с вашими комплексами и вы пытаетесь здесь их скомпенсировать. Но вы до сих пор не научились выделять фрагменты текстов комментариев, которые вы цитируете. Вас можно пожалеть (девочки точно не любят), но вы постоянно спамите на форуме и скоро переполните его базу  :smile: .  Меня это беспокоит и только поэтому я на вас реагирую  :smile: .
 
попроще можно сказать что и main и OnStop исполняются (вызываются) под единым мьютексом.
который снимается всего двумя способами
а) выходом из функции
б) обращением к С-function
и sleep - это вариант б)

при б) мьютекс снимается на входе в С-функцию и возвращается при возвращении из неё.
при этом если С-функция в свою очередь обратится в Lua, то мьютекс тоже будет выставлен на время такого обращения и снимется при возврате в С функцию
отличие между Lua и С-функцией определяется через lua_iscfunction

в Quik Lua почти всё C-функции.
поэтому sleep(0) можно заменить, например, tostring, да и pcall тоже С-функция, так что наверно в main сработало бы pcall(run) без флагов
 
_sk_, добрый день.

Реализация Lua-машины такова, что перед входом в главный цикл интерпретатора объект синхронизации захватывается и отпускается только в некоторых случаях, например, при вызове внешних функций (в частности, sleep). Рекомендуем использовать вызов функции sleep() внутри цикла, чтобы исключить зависание приложения.
 
Цитата
TGB написал:
Цитата
nikolz написал:
_sk_ ,вот Ваш тест с исправленными Вашими ошибками. Работает без проблем.
    Вы до сих пор не поняли, что у _sk_ нет проблем со скритом ( он делает flag  =   true и все у него хорошо ). Его интерисует странное поведение скрипта когда flag =false и это нормально.
  Вообще, из того что видно невооруженным взглядом, у вас постоянный зуд отметиться на форуме (как у собачки, выпущенной на прогулку  :: ). Зачем вы работаете на форуме «прокладкой» между комментариями?
  Явно, что у вас проблемы с вашими комплексами и вы пытаетесь здесь их скомпенсировать. Но вы до сих пор не научились выделять фрагменты текстов комментариев, которые вы цитируете. Вас можно пожалеть (девочки точно не любят), но вы постоянно спамите на форуме и скоро переполните его базу  :: .  Меня это беспокоит и только поэтому я на вас реагирую  :: .
Вы не поняли, я исправил у него ошибки и можете делать хоть faLSE  
 
TGB,
исправленный скрипт не виснет
Вы вместо брызжания проверьте тест.
-------------------
если есть другие проблемы , то пишите я исправлю.
----------------------
И очевидно, и у кого что болит тот о том и говорит
 
_sk_,
Вы не ответили, я исправил Ваш тест.
Что теперь не так?
 
Цитата
Anton Belonogov написал:
_sk_, добрый день.

Реализация Lua-машины такова, что перед входом в главный цикл интерпретатора объект синхронизации захватывается и отпускается только в некоторых случаях, например, при вызове внешних функций (в частности, sleep). Рекомендуем использовать вызов функции sleep() внутри цикла, чтобы исключить зависание приложения.
Спасибо за пояснения о ттехподдержки. Хорошо, что они совпадают с теми, что высказали другие участники общения в этой теме.
 
Цитата
nikolz написал:
_sk_,
Вы не ответили, я исправил Ваш тест.
Что теперь не так?
У меня всё хорошо, спасибо.
Страницы: 1
Читают тему
Наверх