Quik 8.6 Critical error ACCESS_VIOLATION

Страницы: 1
RSS
Quik 8.6 Critical error ACCESS_VIOLATION
 
Столкнулся с проблемой при работе с тиками через CreateDataSource.

Запускаешь квик, таблица обезличенных сделок пока пустая (удалить alltrade.dat для воспроизведения), квик начинает быстро грузить сделки.
В это время работает мой скрипт, который берет данные тиков, например ds:T(i), ds:V(i).
Скрипт падает в ошибку: Critical error ACCESS_VIOLATION in script C:\LuaScripts\TestQuikLua\test_ds5.lua
Ошибка возникает во второй половине дня, когда новых тиков много и квик долго их прокачивает.
Т.е. проблема когда квик активно закачивает сделки и скрипт работает с DataSource.
Воспроизводится в 8.5.2 и 8.6. До версии 8.5 данной проблемы не было.

Код скрипта для воспроизведения:
Код
is_run = true

function main()
    message("start", 1)
    while is_run do
        TestDS("RIM0")
        sleep(10)
    end;
end

function OnStop()
    message("stop", 1)
    is_run = false
end

function TestDS(tiker)
    local ds, errorDescr = CreateDataSource("SPBFUT", tiker, 0)
    local size = ds:Size()
    for i = 0, size do
        local time = ds:T(i)
    end
    message("DS " .. tiker .. " " .. size, 0)
end
 
Наглядное пособие "как прострелить себе ногу". Вы в цикле каждые 10мс создаете новый датасорец и потом внутри в еще одном цикле весь его просматриваете. Удивительно не то, что в 8.5.2 и далее крэшится, удивительно, что раньше не крэшилось.
 
А зачем Вы каждый раз создаете источник данных? Он же память будет отъедать.
 
Это был тестовый пример для воспроизведения, рабочий код другой, и там вызывается намного реже код подсчета, но при этом падает.
Можно и один раз создать DataSource и все равно падает.
Код
is_run = true

function main()
    message("start", 1)
    local ds, errorDescr = CreateDataSource("SPBFUT", "RIM0", 0)
    while is_run do
        TestDS(ds)
        sleep(10)
    end;
end

function OnStop()
    message("stop", 1)
    is_run = false
end

function TestDS(ds)
    local size = ds:Size()
    for i = 0, size do
        local time = ds:T(i)
    end
    message("DS " .. size, 0)
end
 
Цитата
Андрей написал:
for i = 0, size do
Код
for i = 0, size - 1 do
 
Цитата
Anton написал:
for i = 0, size - 1 do
Справедливо, но тоже падает (Critical error ACCESS_VIOLATION).  
 
Ну еще SetEmptyCallback надо дернуть. Ежли будет таки падать, арке карты в руки.
 
Цитата
Anton написал:
Ну еще SetEmptyCallback надо дернуть
Это не помогло.
 
Какой бы из вариантов не использовался, если запуск скрипта ведёт к падению терминала -- это хороший способ указать его разработчикам, где ошибка. Неоптимальные скрипты в этом смысле хороши, что напрягают систему и выявляют ошибки гораздо быстрее. Терминал же всегда должен без ACCESS_VIOLATION работать при синтаксически корректном коде скрипта.
 
Цитата
_sk_ написал:
Терминал же всегда должен без ACCESS_VIOLATION работать при синтаксически корректном коде скрипта.
Он ловит этот акцесс виолейшен, останавливает скрипт и показывает эту ошибку, так что в этом смысле все ок. А вот что этот акцесс виолейшен там есть (а он есть, проверил), это косячок-с. Случается на доступе к ds:T(i) непосредственно после подключения. Очевидно, после подключения датасорец очищается и начинает заполняться заново, в итоге скрипт лезет дальше его конца, поскольку уже сохранил размер до подключения.
 
Я во всех своих скриптах при доступе к datasource-объектам внутри main применяю примерно такие фрагменты кода, чтобы во время доступа к datasource его содержимое внезапно не изменилось:
Код
local function getRawCandles(ds, maxSize)
    local size = 0
    local T, O, H, L, C, V = {}, {}, {}, {}, {}, {}

    if ds and ds:Size() > 0 then
        table.ssort({ 0, 1 }, function(a, b)
            local dsSize = ds:Size()
            if maxSize == nil then
                maxSize = dsSize
            end
            local count, offset
            if dsSize <= maxSize then
                count, offset = dsSize, 0
            else
                count, offset = maxSize, dsSize - maxSize
            end
            for i = 1, count do
                local j = i + offset
                T[i] = ds:T(j)
                O[i] = ds:O(j)
                H[i] = ds:H(j)
                L[i] = ds:L(j)
                C[i] = ds:C(j)
                V[i] = ds:V(j)
            end
            size = count
            return true
        end)
    end
    return { size = size, T = T, O = O, H = H, L = L, C = C, V = V, }
end
Недостатком является блокировка потока коллбэков, что плохо в случае большого количества скриптов и одновременных запросов данных из datasource.

Но что делать, если такая архитектура терминала?
 
Т.к. данные приходят с сервера (а мгновенно это никто гарантировать не может), то надо ждать загрузки всех данных (всех баров).
Да, ошибка бывает когда обращаешься к пустому Size. Правда падать, вроде как, не должен.

Проблема ожидания не только в том, что надо ждать, а в том, что интерфейс не дает возможности понять: а все ли данные приехали. Этот ds:Size() - это уже точно все или мы еще в процессе. Бывало не раз когда Size() уже не 0, но и не последний.
Я для себя сделал процедуру, сравнивающую время последней сделк и время последнего бара, чтобы понимать, что уже все загружено.
Но и здесь проблема - нету у нас даты последней сделки, есть только время (уже поднимал этот вопрос). Вот и получается, что для "дырявых" малоликвидных инструментов возможны проблемы определения состояния загружены все данные или нет.
 
Цитата
_sk_ написал:
чтобы во время доступа к datasource его содержимое внезапно не изменилось
Попробовал (по-своему, но тоже под локом), то же самое. По моим представлениям базовые вещи сделаны уровнем ниже, главный поток получает уведомления оттуда, соответственно лок не дает ему это уведомление получить, но само действие таки происходит. Поэтому где-то лок помогает (когда данные берутся из таблицы, живущей в главном потоке), где-то нет (когда напрямую из хранилища). Хороший эксперимент - повесить весь юай на локе при подключенном сервере, данные продолжают себе ехать, файлы растут, хотя квик висит намертво.
 
А теперь хотелось бы увидеть ответ от разработчиков терминала, что они по этому поводу думают.

1) Считается ли проблемой ACCESS_VIOLATION, упомянутый выше?

2) Как пользователям корректно сделать цикл по всем имеющимся данным внутри DataSource, чтобы не нарваться в процессе итерирования на изменение данных из-за поступившей новой рыночной информации или очистки объекта DataSource?
 
Еще немного потестировал.
Падает не только при полной прокачке тиков, но и при получении новых тиков тоже.
Запустил квик, дождался когда прокачаются тики и начнут новые тики приходить, запускаю скрипт, через некоторое время падает с этой же ошибкой.

Еще пытался понять на каком i падает, нет зависимости, на разном i падает, в начале, в середине, в конце.
 
Чисто из головы немного рассуждений. Тиковый датасорец берет данные из таблицы всех сделок, таблица всех сделок мэпится в память блоками по 64к. Когда таблица перерастает очередную границу, мэппинг прибивается и создается новый побольше. Предположение: датасорец лезет в мэппинг, который уже прибит из-за прихода очередного тика, т.е. либо он кэширует указатель, либо это проблема с синхронизацией, когда другой поток начинает пересоздавать мэппинг прямо под лезущим в него потоком скрипта.
 
Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
 
Цитата
_sk_ написал:
Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Здравствуйте!

Ваше обращение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
 
Здравствуйте, на версии 8.6.097, проблема с general protection fault с версии 8.5 никуда не исчезла! Продолжает валиться квик на рабочих lua скриптах с версии 7.27.1. Произвольно, иногда при запуске сразу, иногда через небольшое время. Дамп, скрины отправил в поддержку, уже второй раз!

Скрипты поменял, учел изменения в lua 5.3, никаких подключаемых внешних библиотек нет, только код. Отправлять саппорту терминал со всеми скриптами не вариант!

Это же жесть!! Ранее эксперименты с квиком можно было игнорировать, не участвуя в сырой отладке на пользователях, оставаясь на старой версии, а теперь через пару недель запустят изменения на бирже, на версии 7 оставаться, как пишет саппорт нельзя, новая валится, что делать?????
 
Цитата
Евгений Петров написал:
Здравствуйте, на версии 8.6.097, проблема с general protection fault с версии 8.5 никуда не исчезла! Продолжает валиться квик на рабочих lua скриптах с версии 7.27.1. Произвольно, иногда при запуске сразу, иногда через небольшое время. Дамп, скрины отправил в поддержку, уже второй раз!

Скрипты поменял, учел изменения в lua 5.3, никаких подключаемых внешних библиотек нет, только код. Отправлять саппорту терминал со всеми скриптами не вариант!

Это же жесть!! Ранее эксперименты с квиком можно было игнорировать, не участвуя в сырой отладке на пользователях, оставаясь на старой версии, а теперь через пару недель запустят изменения на бирже, на версии 7 оставаться, как пишет саппорт нельзя, новая валится, что делать?????
Добрый день.

Если вы нам присылали dmp, то Вам должны были обращению присвоить CQ. Если так, то ожидайте ответ.
 
Цитата
_sk_ написал:
Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Добрый день,
     
      Описанная в данном инциденте ошибка возникает из-за проблемы       синхронизации доступа к данным из Lua-скрипта и будет исправлена в       одной из ближайших очередных версий программы.
      Приносим извинения за причиненные неудобства.
 
Цитата
Egor Zaytsev написал:
Цитата
_sk_ написал:
Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Добрый день,
     
      Описанная в данном инциденте ошибка возникает из-за проблемы       синхронизации доступа к данным из Lua-скрипта и будет исправлена в       одной из ближайших очередных версий программы.
      Приносим извинения за причиненные неудобства
В версии 8.7.1.3 проблема осталась
 
Цитата
Сергей написал:
В версии 8.7.1.3 проблема осталась
исправления еще не было.
 
столкнулся  с такой же проблемой. исправление еще не реализовано? если реализовано то с какой версии? у сбербанка последня 8.7.1.3 как раз..
 
Цитата
mefisto mefisto написал:
столкнулся  с такой же проблемой. исправление еще не реализовано? если реализовано то с какой версии? у сбербанка последня 8.7.1.3 как раз..
Добрый день.

К сожалению, ошибка еще не исправлена.

Мы сообщим в данной ветке форума, когда выйдет версия с исправленной проблемой.
 

Андрей написал:
Воспроизводится в 8.5.2 и 8.6. До версии 8.5 данной проблемы не было.

----

Андрей написал:
тоже падает (Critical error ACCESS_VIOLATION).  

----

Евгений Петров написал:
на версии 8.6.097, проблема с general protection fault с версии 8.5 никуда не исчезла! Продолжает валиться квик на рабочих lua скриптах с версии 7.27.1. Произвольно, иногда при запуске сразу, иногда через небольшое время.

--------------------------------------
    Не буду утверждать стопудово, но многие ситуации в версиях QUIK >= 8.5, скорее всего, связаны с тем, что в этих версиях возникают ошибки реализации АРКОй QLua-машины 5.3.5 (отличной от нативной Lua-машины 5.3.5). Это отличие связано с тем, что QLua-машина 5.3.5 должна быть потокобезопасной, по сравнению с однопоточной Lua-машиной 5.3.5 (о причинах этого можно почитать мой комментарий № 142 по ссылке: https://forum.quik.ru/forum10/topic5119/?PAGEN_1=3).
   Более определенно, могу утверждать, что мой тест (многопоточный) автоматического управления памятью QLua-машины 5.3.5, для всех существующих (на дату 07.09.20) версий QUIK >= 8.5 диагностирует, в интервале 5 минут (в произвольные моменты), ее сбои (похоже, вызванные ошибками в синхронизации) и утечку памяти. Поддержке QUIK мною, начиная с 25.05.20, выслано более 40 дампов, а 15.08.20 выслан и сам тест для возможности оперативной отладки разработчиками новых версий QUIK. Для версий QUIK < 8.5 этот тест, ошибок не обнаруживает.
   Представьте себе, что на вашем ПК очень часто сбоит RAM (память). При этом любые ваши программы могут падать в любом месте, и можно искать в них свои ошибки до «посинения» (сам я этим не занимаюсь, до тех пор, пока не будут устранены сбои автоматического управления памятью QLua-машины 5.3.5).

 
также в одном из скриптов у меня вылетает эта ошибка сразу же как я подключаю lsqlite3 библиотеку

require "lsqlite3"

в данном случае ошибка означает тоже самое или можно как то обойти? раньше на 8.3 кажется все отлично подключалось
 
Цитата
mefisto mefisto написал:
также в одном из скриптов у меня вылетает эта ошибка сразу же как я подключаю lsqlite3 библиотеку

require "lsqlite3"

в данном случае ошибка означает тоже самое или можно как то обойти? раньше на 8.3 кажется все отлично подключалось
Добрый день.

Скорее всего тоже самое, но попробуйте вместо функции require использовать package.loadlib
 
Сегодня тоже первый раз (за все время использования версий > 8.5) словил такую ошибку на 8.8.4.3.

При этом это не тики, а M5, и произошла она на уже загруженных данных. Т.е. это была новая порция, скорее всего. Индекс бара фиксируется в переменной перед чтением.

Скрипт упал, хотя часть кода работы с свечками обернута pcall.

С другой стороны, никакой доп. информации нет, поэтому пока могу предположить, что это именно доступ к барам, как и в примере выше. Но кто знает, что это было на самом деле.
Хотелось бы, конечно, чтобы секции pcall давали больше информации.
 
Отмена тревоги.
В одном месте была ошибка вызова. Вместо ds:C() вызвано ds:Close().
 
Цитата
Nikolay написал:
Скрипт упал, хотя часть кода работы с свечками обернута pcall.
Неудивительно, если в колбеке, там разные пути для луа-ошибок и исключений, вторые пролетают мимо pcall. Как-то примерно так все колбеки вызываются
Код
static void translator(unsigned int code, struct EXCEPTION_POINTERS * p)
{
   throw seh_exception(code, p);
}

int QLuaScript::execute_lua_callback(lua_State * s, int nargs, int nresults)
{
   int ret = 0;
   _se_translator_function pfn = _set_se_translator(translator);
   try
   {
      ret = lua_pcall(s, nargs, nresults, 0);
      _set_se_translator(pfn);
   }
   catch(const std::exception & ex)
   {
      sprintf(this->error_desc, "%s", ex.what());
      this->kill_script();
      _set_se_translator(pfn);
      ret = ???;
   }
   catch(const seh_exception & ex)
   {
      sprintf(this->error_desc, "Critical error %s in script %s",
         ex.code_as_string(), this->script_name);
      this->kill_script();
      _set_se_translator(pfn);
      ret = ???;
   }
   return ret;
}
Обратите внимание, в ловушках скрипт прибивается, а при ошибке в pcall - нет. Трудно понять, зачем так сделано.
 
Кажется, нашел дырочку, через которую квик может падать при ошибке в скрипте. Вышеприведенная функция вызывается со всеми (?) колбеками по одной схеме, примерно так
Код
int top = lua_gettop(pstate);
lua_getglobal(pstate, "CallbackName");
push_callback_arguments(pstate);
if(this->execute_lua_callback(pstate, nargs, 0))
  quik->show_message(make_error_text(), 3);
// вот тут интересно
if(pstate)
  lua_settop(pstate, top);
Как мы видели выше, при некоторых ошибках квик прибивает скрипт, то есть стейт к моменту вызова lua_settop уже неживой. А проверяется перед вызовом сохраненный локально указатель, который, конечно, как был не-null, так и остался. Возможно, это компилятор наоптимизировал. В каких колбеках ни посмотри - одно и то же.
 
Нет, не в колбеках.

Вот схематичный скрипт, падающий с этой ошибкой.

Код
local sleep  = _G.sleep
local isRun  = true

function _G.main()

    local sec_code = 'SRZ0'
    local class_code = 'SPBFUT'

    local ds = _G.CreateDataSource(class_code, sec_code, _G.INTERVAL_M5)
    if not ds then
        isRun = false
    end

    local index = 0
    if isRun then
        while isRun do
            local last = ds:Size()
            if last ~= 0 then
                while index < last-1 do
                    index = index + 1
                    ds:T(index)
                end
                ds:Close(last)
                ds:T(last)
            end
            sleep(100)
        end
    end
end

Он с ошибкой, как у меня было (Close вместо C). Но хотелось бы внятного сообщения, типа - попытка индексировать значение nil.

И еще особенность: скрипт, упавший с этой ошибкой повторно не запустить, кнопка "Запустить" не активна. Приходится удалять и заново добавлять.
 
Цитата
Nikolay написал:
Нет, не в колбеках.
При ближайшем рассмотрении оказывается, что мейн тоже вызывается по той же схеме, только из своего потока, для него тоже все в силе.

Цитата
Nikolay написал:
Вот схематичный скрипт, падающий с этой ошибкой.
Ну так да, квик лезет куда-то по прибитому указателю и получается акцесс виолешен (уже не в луа, а в самом квике), а он идет мимо pcall, как выше видно.

В учебно-тренировочном хосте с обычным луа 5.3 попробовал генерировать и плюсовые, и seh исключения в скрипте, так их pcall чудесно отлавливает, только что содержательных описаний не выводит, в первом случае "возможно необработанное исключение", во втором просто "объект ошибки не предоставлен". Помнится, раньше квик тоже похожие сообщения выводил в некоторых случаях, то есть ловились они прекрасно pcall'ом. Как теперь получается, что av пролетает мимо pcall, вот вопрос интересный.

Цитата
Nikolay написал:
И еще особенность: скрипт, упавший с этой ошибкой повторно не запустить, кнопка "Запустить" не активна. Приходится удалять и заново добавлять.
Ага, есть такое.
 
Цитата
Nikolay написал:
Нет, не в колбеках.

Вот схематичный скрипт, падающий с этой ошибкой.

Код
   local   sleep    =  _G. sleep 
 local  isRun   =   true 

 function   _G.main ()

     local  sec_code  =   'SRZ0' 
     local  class_code  =   'SPBFUT' 

     local  ds  =   _G.CreateDataSource (class_code, sec_code, _G.INTERVAL_M5)
     if   not  ds  then 
        isRun  =   false 
     end 

     local  index  =   0 
     if  isRun  then 
         while  isRun  do 
             local  last  =  ds: Size ()
             if  last ~ =   0   then 
                 while  index  <  last -  1   do 
                    index  =  index  +   1 
                    ds:T(index)
                 end 
                ds: Close (last)
                ds:T(last)
             end 
             sleep ( 100 )
         end 
     end 
 end 

  
Он с ошибкой, как у меня было (Close вместо C). Но хотелось бы внятного сообщения, типа - попытка индексировать значение nil.

И еще особенность: скрипт, упавший с этой ошибкой повторно не запустить, кнопка "Запустить" не активна. Приходится удалять и заново добавлять.
Здравствуйте!

Ваше обращение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
 
Это не связано с вызовом CreateDataSource. Точно такая же ошибка была получена 25.09.2020 на вызовах OnAllTrade в 10:12:38 (последняя обработанная запись). Инструмент RIZ0. Терминал 8.7.0.6. До этого два или три года на версии 7 скрипт ни разу не зависал. И три или четыре дня, т.е. с 22.09.2020 тоже работал без сбоев, на этом же терминале 8.7.0.6. В Квике выглядит как остановленный скрипт, т.е. с "красным квадратиком". Кнопки "Запустить" и "Остановить" - не активны. Если это поможет, то в main пусто (только цикл для isRun), а прямо в OnAllTrade примерно 15 строчек кода. Вызов CreateDataSource отсутствует.
 
Цитата
MG написал:
Это не связано с вызовом CreateDataSource. Точно такая же ошибка была получена 25.09.2020 на вызовах OnAllTrade в 10:12:38 (последняя обработанная запись). Инструмент RIZ0. Терминал 8.7.0.6. До этого два или три года на версии 7 скрипт ни разу не зависал. И три или четыре дня, т.е. с 22.09.2020 тоже работал без сбоев, на этом же терминале 8.7.0.6. В Квике выглядит как остановленный скрипт, т.е. с "красным квадратиком". Кнопки "Запустить" и "Остановить" - не активны. Если это поможет, то в main пусто (только цикл для isRun), а прямо в OnAllTrade примерно 15 строчек кода. Вызов CreateDataSource отсутствует.
Добрый день.

Как раз с этим вопросом мы и занимаемся. Как будет результат дадим здесь ответ.
 
У меня QLua валится при вызове Close(). Иногда срабатывает, но чаще ACCESS_VIOLATION.
 
Цитата
Александр написал:
У меня QLua валится при вызове Close(). Иногда срабатывает, но чаще ACCESS_VIOLATION.
У меня ошибка со стеком была.
 
_sk_, добрый день!

Описанная в данном инциденте ошибка была исправлена в версии 8.9.0 терминала QUIK. Рекомендуем вам обновить версию программы.
Приносим извинения за причиненные неудобства.
Страницы: 1
Читают тему
Наверх