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-скрипта и будет исправлена в       одной из ближайших очередных версий программы.
      Приносим извинения за причиненные неудобства.
Страницы: 1
Читают тему (гостей: 1)
Наверх