Столкнулся с проблемой при работе с тиками через 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
Пользователь
Сообщений: Регистрация: 21.08.2015
04.06.2020 14:36:43
Наглядное пособие "как прострелить себе ногу". Вы в цикле каждые 10мс создаете новый датасорец и потом внутри в еще одном цикле весь его просматриваете. Удивительно не то, что в 8.5.2 и далее крэшится, удивительно, что раньше не крэшилось.
Пользователь
Сообщений: Регистрация: 27.01.2017
04.06.2020 14:39:07
А зачем Вы каждый раз создаете источник данных? Он же память будет отъедать.
Пользователь
Сообщений: Регистрация: 17.12.2019
04.06.2020 14:55:38
Это был тестовый пример для воспроизведения, рабочий код другой, и там вызывается намного реже код подсчета, но при этом падает. Можно и один раз создать 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
Справедливо, но тоже падает (Critical error ACCESS_VIOLATION).
Пользователь
Сообщений: Регистрация: 21.08.2015
04.06.2020 15:11:01
Ну еще SetEmptyCallback надо дернуть. Ежли будет таки падать, арке карты в руки.
Пользователь
Сообщений: Регистрация: 17.12.2019
04.06.2020 15:55:34
Цитата
Anton написал: Ну еще SetEmptyCallback надо дернуть
Это не помогло.
Пользователь
Сообщений: Регистрация: 31.01.2015
04.06.2020 17:00:01
Какой бы из вариантов не использовался, если запуск скрипта ведёт к падению терминала -- это хороший способ указать его разработчикам, где ошибка. Неоптимальные скрипты в этом смысле хороши, что напрягают систему и выявляют ошибки гораздо быстрее. Терминал же всегда должен без ACCESS_VIOLATION работать при синтаксически корректном коде скрипта.
Пользователь
Сообщений: Регистрация: 21.08.2015
04.06.2020 17:34:45
Цитата
_sk_ написал: Терминал же всегда должен без ACCESS_VIOLATION работать при синтаксически корректном коде скрипта.
Он ловит этот акцесс виолейшен, останавливает скрипт и показывает эту ошибку, так что в этом смысле все ок. А вот что этот акцесс виолейшен там есть (а он есть, проверил), это косячок-с. Случается на доступе к ds:T(i) непосредственно после подключения. Очевидно, после подключения датасорец очищается и начинает заполняться заново, в итоге скрипт лезет дальше его конца, поскольку уже сохранил размер до подключения.
Пользователь
Сообщений: Регистрация: 31.01.2015
04.06.2020 18:23:14
Я во всех своих скриптах при доступе к 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.
Но что делать, если такая архитектура терминала?
Пользователь
Сообщений: Регистрация: 27.01.2017
04.06.2020 19:52:46
Т.к. данные приходят с сервера (а мгновенно это никто гарантировать не может), то надо ждать загрузки всех данных (всех баров). Да, ошибка бывает когда обращаешься к пустому Size. Правда падать, вроде как, не должен.
Проблема ожидания не только в том, что надо ждать, а в том, что интерфейс не дает возможности понять: а все ли данные приехали. Этот ds:Size() - это уже точно все или мы еще в процессе. Бывало не раз когда Size() уже не 0, но и не последний. Я для себя сделал процедуру, сравнивающую время последней сделк и время последнего бара, чтобы понимать, что уже все загружено. Но и здесь проблема - нету у нас даты последней сделки, есть только время (уже поднимал этот вопрос). Вот и получается, что для "дырявых" малоликвидных инструментов возможны проблемы определения состояния загружены все данные или нет.
Пользователь
Сообщений: Регистрация: 21.08.2015
04.06.2020 20:16:01
Цитата
_sk_ написал: чтобы во время доступа к datasource его содержимое внезапно не изменилось
Попробовал (по-своему, но тоже под локом), то же самое. По моим представлениям базовые вещи сделаны уровнем ниже, главный поток получает уведомления оттуда, соответственно лок не дает ему это уведомление получить, но само действие таки происходит. Поэтому где-то лок помогает (когда данные берутся из таблицы, живущей в главном потоке), где-то нет (когда напрямую из хранилища). Хороший эксперимент - повесить весь юай на локе при подключенном сервере, данные продолжают себе ехать, файлы растут, хотя квик висит намертво.
Пользователь
Сообщений: Регистрация: 31.01.2015
05.06.2020 06:08:40
А теперь хотелось бы увидеть ответ от разработчиков терминала, что они по этому поводу думают.
1) Считается ли проблемой ACCESS_VIOLATION, упомянутый выше?
2) Как пользователям корректно сделать цикл по всем имеющимся данным внутри DataSource, чтобы не нарваться в процессе итерирования на изменение данных из-за поступившей новой рыночной информации или очистки объекта DataSource?
Пользователь
Сообщений: Регистрация: 17.12.2019
05.06.2020 12:50:33
Еще немного потестировал. Падает не только при полной прокачке тиков, но и при получении новых тиков тоже. Запустил квик, дождался когда прокачаются тики и начнут новые тики приходить, запускаю скрипт, через некоторое время падает с этой же ошибкой.
Еще пытался понять на каком i падает, нет зависимости, на разном i падает, в начале, в середине, в конце.
Пользователь
Сообщений: Регистрация: 21.08.2015
05.06.2020 15:24:53
Чисто из головы немного рассуждений. Тиковый датасорец берет данные из таблицы всех сделок, таблица всех сделок мэпится в память блоками по 64к. Когда таблица перерастает очередную границу, мэппинг прибивается и создается новый побольше. Предположение: датасорец лезет в мэппинг, который уже прибит из-за прихода очередного тика, т.е. либо он кэширует указатель, либо это проблема с синхронизацией, когда другой поток начинает пересоздавать мэппинг прямо под лезущим в него потоком скрипта.
Пользователь
Сообщений: Регистрация: 31.01.2015
05.06.2020 16:33:14
Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
QUIK clients support
Сообщений: Регистрация: 27.01.2015
08.06.2020 08:21:32
Цитата
_sk_ написал: Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Здравствуйте!
Ваше обращение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Пользователь
Сообщений: Регистрация: 17.04.2015
08.06.2020 10:30:21
Здравствуйте, на версии 8.6.097, проблема с general protection fault с версии 8.5 никуда не исчезла! Продолжает валиться квик на рабочих lua скриптах с версии 7.27.1. Произвольно, иногда при запуске сразу, иногда через небольшое время. Дамп, скрины отправил в поддержку, уже второй раз!
Скрипты поменял, учел изменения в lua 5.3, никаких подключаемых внешних библиотек нет, только код. Отправлять саппорту терминал со всеми скриптами не вариант!
Это же жесть!! Ранее эксперименты с квиком можно было игнорировать, не участвуя в сырой отладке на пользователях, оставаясь на старой версии, а теперь через пару недель запустят изменения на бирже, на версии 7 оставаться, как пишет саппорт нельзя, новая валится, что делать?????
QUIK clients support
Сообщений: Регистрация: 27.01.2015
08.06.2020 10:50:42
Цитата
Евгений Петров написал: Здравствуйте, на версии 8.6.097, проблема с general protection fault с версии 8.5 никуда не исчезла! Продолжает валиться квик на рабочих lua скриптах с версии 7.27.1. Произвольно, иногда при запуске сразу, иногда через небольшое время. Дамп, скрины отправил в поддержку, уже второй раз!
Скрипты поменял, учел изменения в lua 5.3, никаких подключаемых внешних библиотек нет, только код. Отправлять саппорту терминал со всеми скриптами не вариант!
Это же жесть!! Ранее эксперименты с квиком можно было игнорировать, не участвуя в сырой отладке на пользователях, оставаясь на старой версии, а теперь через пару недель запустят изменения на бирже, на версии 7 оставаться, как пишет саппорт нельзя, новая валится, что делать?????
Добрый день.
Если вы нам присылали dmp, то Вам должны были обращению присвоить CQ. Если так, то ожидайте ответ.
QUIK clients support
Сообщений: Регистрация: 27.01.2015
15.06.2020 10:12:10
Цитата
_sk_ написал: Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Добрый день,
Описанная в данном инциденте ошибка возникает из-за проблемы синхронизации доступа к данным из Lua-скрипта и будет исправлена в одной из ближайших очередных версий программы. Приносим извинения за причиненные неудобства.
написал: Пока не теряю надежду, что разработчики ответят на поставленные выше вопросы.
Добрый день,
Описанная в данном инциденте ошибка возникает из-за проблемы синхронизации доступа к данным из Lua-скрипта и будет исправлена в одной из ближайших очередных версий программы. Приносим извинения за причиненные неудобства
В версии 8.7.1.3 проблема осталась
Пользователь
Сообщений: Регистрация: 23.01.2015
14.07.2020 16:33:17
Цитата
Сергей написал: В версии 8.7.1.3 проблема осталась
исправления еще не было.
Пользователь
Сообщений: Регистрация: 26.06.2017
07.09.2020 19:50:23
столкнулся с такой же проблемой. исправление еще не реализовано? если реализовано то с какой версии? у сбербанка последня 8.7.1.3 как раз..
QUIK clients support
Сообщений: Регистрация: 27.01.2015
08.09.2020 05:25:40
Цитата
mefisto mefisto написал: столкнулся с такой же проблемой. исправление еще не реализовано? если реализовано то с какой версии? у сбербанка последня 8.7.1.3 как раз..
Добрый день.
К сожалению, ошибка еще не исправлена.
Мы сообщим в данной ветке форума, когда выйдет версия с исправленной проблемой.
Пользователь
Сообщений: Регистрация: 12.05.2020
08.09.2020 06:06:06
Андрей написал: Воспроизводится в 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 по ссылке: . Более определенно, могу утверждать, что мой тест (многопоточный) автоматического управления памятью 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).
Пользователь
Сообщений: Регистрация: 26.06.2017
08.09.2020 08:32:04
также в одном из скриптов у меня вылетает эта ошибка сразу же как я подключаю lsqlite3 библиотеку
require "lsqlite3"
в данном случае ошибка означает тоже самое или можно как то обойти? раньше на 8.3 кажется все отлично подключалось
QUIK clients support
Сообщений: Регистрация: 27.01.2015
08.09.2020 14:27:28
Цитата
mefisto mefisto написал: также в одном из скриптов у меня вылетает эта ошибка сразу же как я подключаю lsqlite3 библиотеку
require "lsqlite3"
в данном случае ошибка означает тоже самое или можно как то обойти? раньше на 8.3 кажется все отлично подключалось
Добрый день.
Скорее всего тоже самое, но попробуйте вместо функции require использовать package.loadlib
Пользователь
Сообщений: Регистрация: 27.01.2017
21.09.2020 12:46:11
Сегодня тоже первый раз (за все время использования версий > 8.5) словил такую ошибку на 8.8.4.3.
При этом это не тики, а M5, и произошла она на уже загруженных данных. Т.е. это была новая порция, скорее всего. Индекс бара фиксируется в переменной перед чтением.
Скрипт упал, хотя часть кода работы с свечками обернута pcall.
С другой стороны, никакой доп. информации нет, поэтому пока могу предположить, что это именно доступ к барам, как и в примере выше. Но кто знает, что это было на самом деле. Хотелось бы, конечно, чтобы секции pcall давали больше информации.
Пользователь
Сообщений: Регистрация: 27.01.2017
21.09.2020 14:35:31
Отмена тревоги. В одном месте была ошибка вызова. Вместо ds:C() вызвано ds:Close().
Пользователь
Сообщений: Регистрация: 21.08.2015
23.09.2020 04:42:20
Цитата
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 - нет. Трудно понять, зачем так сделано.
Пользователь
Сообщений: Регистрация: 21.08.2015
23.09.2020 07:46:09
Кажется, нашел дырочку, через которую квик может падать при ошибке в скрипте. Вышеприведенная функция вызывается со всеми (?) колбеками по одной схеме, примерно так
Код
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, так и остался. Возможно, это компилятор наоптимизировал. В каких колбеках ни посмотри - одно и то же.
Пользователь
Сообщений: Регистрация: 27.01.2017
23.09.2020 09:34:19
Нет, не в колбеках.
Вот схематичный скрипт, падающий с этой ошибкой.
Код
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 написал: Вот схематичный скрипт, падающий с этой ошибкой.
Ну так да, квик лезет куда-то по прибитому указателю и получается акцесс виолешен (уже не в луа, а в самом квике), а он идет мимо pcall, как выше видно.
В учебно-тренировочном хосте с обычным луа 5.3 попробовал генерировать и плюсовые, и seh исключения в скрипте, так их pcall чудесно отлавливает, только что содержательных описаний не выводит, в первом случае "возможно необработанное исключение", во втором просто "объект ошибки не предоставлен". Помнится, раньше квик тоже похожие сообщения выводил в некоторых случаях, то есть ловились они прекрасно pcall'ом. Как теперь получается, что av пролетает мимо pcall, вот вопрос интересный.
Цитата
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.
И еще особенность: скрипт, упавший с этой ошибкой повторно не запустить, кнопка "Запустить" не активна. Приходится удалять и заново добавлять.
Здравствуйте!
Ваше обращение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Пользователь
Сообщений: Регистрация: 26.09.2020
26.09.2020 02:55:49
Это не связано с вызовом 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 отсутствует.
QUIK clients support
Сообщений: Регистрация: 27.01.2015
28.09.2020 09:51:16
Цитата
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 отсутствует.
Добрый день.
Как раз с этим вопросом мы и занимаемся. Как будет результат дадим здесь ответ.
Пользователь
Сообщений: Регистрация: 21.02.2015
30.09.2020 14:09:03
У меня QLua валится при вызове Close(). Иногда срабатывает, но чаще ACCESS_VIOLATION.
Пользователь
Сообщений: Регистрация: 21.02.2015
30.09.2020 15:16:11
Цитата
Александр написал: У меня QLua валится при вызове Close(). Иногда срабатывает, но чаще ACCESS_VIOLATION.
Описанная в данном инциденте ошибка была исправлена в версии 8.9.0 терминала QUIK. Рекомендуем вам обновить версию программы. Приносим извинения за причиненные неудобства.