Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?

Страницы: 1
RSS
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Столкнулся с таким вот казусом:
Скрипт запускается со стартом Quikа (7.14.1.7), т.е. еще до соединения с сервером.
Однако ничего существенного не делает и ждет OnConnected.
Получив подтверждение связи с сервером, переходит в полноценный режим и начинает, кроме прочего, отрабатывать колбеки OnOrder, OnTrade и т.п., которые вызывает Quik по мере стартового заполнения своих соответствующих таблиц записями о событиях, которые были до включения Quika (мои вчерашние сделки и т.п.)
И тут приходит OnCleanUp...
Ничего, вроде бы, страшного нет, скрипт тоже не слепой, и при необходимости может рестартовать и все заново корректно отработать уже с новой актуальной информацией.

Но вот, что вдруг вылетело:
Скрипт умер внутри колбэка OnTransReply (это был ответ на транзакцию текущего служебного обмена информацией терминала и сервера брокера) на инструкции:
f = tab.brokerref and tab.brokerref:find(TEname)
bad argument #1 to 'find' (string expected, got nil)

где tab - таблица, переданная Quikом в OnTransReply.
Весело получается: когда интерпретатор успешно нашел адрес функции string.find, tab.brokerref еще был строкой, а когда уже стал формировать стек вызова функции find, то tab.brokerref сдох до nil !

Я понимаю, что вероятность второй такой поимки покемона крайне мала, но все же не нулевая.

Уважаемая техподдержка QUIK!
Прошу сделать так, чтобы QUIK, перед очисткой своих внутренних таблиц по OnCleanUp, убедился, что вышел из всех колбеков lua скриптов, и вызывал OnCleanUp скриптов только после завершения своей полной очистки.
Или дайте иное объяснение произошедшего.
 
Добрый день.

Для разбора ситуации, просьба выложить полный скрипт и порядок действий,
который привел к вышеописанной проблеме.  
 
Код
local function Check(tab)
  return tab.brokerref and tab.brokerref:find(TEname) -- умерли здесь
end

function OnTransReply(trans_reply)
-- Для отладки
  if trans_reply.result_msg ~= "Транзакция успешно выполнена." then -- игнорируем служебные транзацкии сбера
    Logt:msg2fileflt(trans_reply, "OnTransReply")
  end
-- !!!!
if Check(trans_reply) or TRCheck(trans_reply) then
    TQ.AddTradeTask(TE.OnTransReplyMain,{trans_reply}) -- помещает в приоритетную очередь задачу вызова обработчика таблицы trans_reply в потоке main
  end
end
Параллельный поток main не еще не имел доступа к таблице trans_reply, поэтому нет смысла его приводить. Другие колбэки, тем более. Косвенным доступом (операциями с глобальным окружением, изменением метатаблиц типов данных и т.п.) скрипт не занимается, таблицу string не переопределяет.
В Logt:msg2fileflt() скрипт не зашел (нет записи в логе, функция всегда заканчивается вызовом io.flush()), следовательно обрабатывалась служебная транзакция обмена информацией терминала и сервера брокера, у которой всегда trans_reply.brokerref == "".

Из текста инструкции
Код
return tab.brokerref and tab.brokerref:find(TEname)
и ошибки
Цитата
bad argument #1 to 'find' (string expected, got nil)
видно, что tab.brokerref не был равен nil, далее, tab.brokerref имел тип string, т.к. интерпретатор успешно обратился к таблице string для индексирования поля find, а вот далее, внутри find, при проверке переданных параметров, обнаружилось, что в качестве первого параметра в стеке оказался nil или ссылка на переменную, содержащую nil, в то время как туда, по идее, должна была быть скопирована ссылка на строку tab.brokerref.
Где-то за секунду до этого в логах был зарегистрирован вызов колбека OnCleanUp(). В момент появления окна с сообщением об ошибке у меня на экране были выведены окна графиков, стакан и таблица текущих торгов. Все они еще были пустыми.
Скрипт работает в неизменном в отношении обработчиков OnCleanUp и OnTransReply виде ежедневно около 4 месяцев, ошибка выскочила впервые. Торги в этот момент еще не шли.
 
После более спокойного, безэмоционального, анализа возник вопрос:
Quik в OnTransReply() (OnOrder, OnTrtade, равно как и в любой другой колбек) передает адрес блока памяти, содержащего (в виде lua таблицы) новую/изменившуюся строку Таблицы Транзакций (Таблицы заявок, Таблицы Сделок и т.д.) или предварительно делает ее копию, и уже ее адрес передает в колбек? Другими словами, передав в колбек какую-либо таблицу, может ли в принципе Quik потом закулисно обратиться/поменять/стереть (по OnCleanUp) содержимое полей этой таблицы?
 
Алексей,

Если данные уже попали в Вашу таблицу, то терминал ее уже не сможет затереть, пока колбек не завершится.
куда бОльшие сомнения вызывает переменная TEname, что это такое?
Было бы удобней увидеть полный код целиком, а не только часть.
 
Уже хотел ответить Вам, что нечего пенять на TEname, поскольку это argument #2 для find, но решил проверить, и с удивлением обнаружил, что для
tab.brokerref:find(TEname) - это argument #1, а для
string.find(tab.brokerref,TEname) - это argument #2,
хотя это идентичные вызовы функции find, и потому я был уверен, что в диагностических сообщениях об ошибках интерпретатор сообщает нумерацию аргументов именно по их расположению в стеке.
Приношу извинения.
Буду искать как слетел в nil TEname...
 
Анализ показал, что при крайне маловероятном стечении обстоятельств (4 месяца 24/7 все работало нормально), может начаться обработка OnTransReply, когда TEname еще не инициализирована.
Но дело в том, что в логах есть запись об инициализации TEname и абсолютно никак после этого она не может измениться.
Причем между записью значения TEname и записью об этом в лог интерпретатор должен выполнить более 200 строк кода, включая создание нового файла, записи в него и гарантированного сброса на диск по flush. Правда все это происходит в потоке main.
Единственным разумным объяснением произошедшего является то, что поток main еще выполняется достаточно долгое время, даже после того, как lua интерпретатор наткнется на критическую ошибку в потоке Quik (в потоке, где выполнялся OnTransReply()).
Такое действительно возможно?
 
Видимо вопрос остался незамеченным.

Из вышеприведенных наблюдений есть основание полагать, что после возникновения в потоке Quik (в колбеке) ошибки исполнения интерпретатора (допустим, деление на 0 или индексирование nil), управление все же может вернуться в поток main, и там еще некоторое время скрипт будет выполняться.

ВОПРОСЫ:
1. Это действительно так?
2. Если так, то есть ли какие-то критерии, по которым можно оценить до каких пор будет работать поток main? (например, 5 секунд или до первого вызова sleep и т.п.)
 
Вы говорите про разные потоки, которые между собой не синхронизируются.
Если в одном потоке случилась ошибка, то второй поток как минимум закончит обработку прежде чем случится выход, либо будет завершен принудительно через 5 сек.
 
Опять столкнулся с этой ошибкой. Но при этом скрипт благополучно продолжил свою работу!
Судя по логам, вызов колбека (в потоке которого случилась ошибка) произошел после OnInit, но РАНЬШЕ старта потока main.
Исходя из этого прошу подтвердить два вывода:

1. Колбеки начинают вызываться после окончания OnInit, но могут выполняться до старта потока main.
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.
 
Цитата
Алексей написал:
1. Колбеки начинают вызываться после окончания OnInit, но могут выполняться до старта потока main.
Колбеки могут начать выполняться до старта main и в этом нет ничего удивительного.
main выполняется после OnInit, остальные колбеки никакого значения не имеют.

Цитата
Алексей написал:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.
Так не должно быть.
Если требуется анализ, приведите полный код скрипта на котором возникает проблема и сообщите версию терминала QUIK
 
Цитата
Sergey Gorokhov написал:
Цитата
Алексей   написал:
1. Колбеки начинают вызываться после окончания OnInit, но могут выполняться до старта потока main.
Колбеки могут начать выполняться до старта main и в этом нет ничего удивительного.
main выполняется после OnInit, остальные колбеки никакого значения не имеют.
 
Цитата
Sergey Gorokhov написал:
Цитата
Алексей   написал:
1. Колбеки начинают вызываться после окончания OnInit, но могут выполняться до старта потока main.
Колбеки могут начать выполняться до старта main и в этом нет ничего удивительного.
main выполняется после OnInit, остальные колбеки никакого значения не имеют.

В этом действительно нет ничего удивительного.
Только вопрос о том, могут или нет колбеки начать выполняться до main, возник потому, что это определяется не какими-то вселенскими правилами реализации многопоточности, а конкретным решением разработчика конкретного программного продукта. Вариант, при котором до страта main не могут вызываться колбеки, тоже имеет право на существование и свою логику для реализации. И глядя на стр. 6 "Использование Lua в Рабочем месте QUIK.pdf" я, по простоте душевной, решил что разработчики Quik руководствовались логикой из второго варианта. И обнаружив обратное, был несколько озадачен.

Цитата
Sergey Gorokhov написал:
Цитата
Алексей   написал:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.
Так не должно быть.
Если требуется анализ, приведите полный код скрипта на котором возникает проблема и сообщите версию терминала QUIK

Однако и к моему удивлению так случилось!
Весь код - более 8 тысяч строк, заставлять Вас его изучать в поисках ошибок мне совесть не позволяет :)
Код же, исполнение которого вызывает ошибку, приведен в посте #3.

Ошибка, напомню, возникает в обработчике OnTransReply, когда происходит обращение к еще не инициализированной TEname, как к строке.
Переменной TEname присваивается строковое значение в самом начале main. (Теперь то я перенес это в OnInit, но на исходное решение были свои соображения).
Однако я столкнулся с необъяснимой ситуацией: в "Ошибки выполнения скрипта" светилось: "bad argument #1 to 'find' (string expected, got nil)", а скрипт прекрасно продолжал свою кипучую деятельность.
Я себе не представляю ситуации, чтобы скрипт при такой ошибке в потоке терминала не был принудительно завершен Quikом, если поток main уже запущен.
Из этого я и сделал предположение №2.
 
Цитата
Алексей написал:
Только вопрос о том, могут или нет колбеки начать выполняться до main, возник потому, что это определяется не какими-то вселенскими правилами реализации многопоточности, а конкретным решением разработчика конкретного программного продукта.

Какими правилами, Вы вообще о чем? Колбеки выполняются по событию.
Событие произошло до main вот и колбек сработал до main.
В чем вопрос, не понятно.
Цитата
Алексей написал:
И глядя на стр. 6 "Использование Lua в Рабочем месте QUIK.pdf"
На стр 6, данного документа рассказано как запустить скрипт Lua.

Что не так?
Цитата
Алексей написал:
Весь код - более 8 тысяч строк, заставлять Вас его изучать в поисках ошибок мне совесть не позволяет :)
И что мешает создать более компактную версию, чисто для воспроизведения описанной проблемы?
И потом, большой код никого из поддержки не пугает. Если Вы считаете его не публичным, всегда можно отправить на quiksupport@arqatech.com

Цитата
Алексей написал:
Код же, исполнение которого вызывает ошибку, приведен в посте #3.
Это не код, а пара строк.
Что такое код, это проект со своей рабочей логикой. Проследив которую можно понять при каких обстоятельствах в указанных строках возможна ошибка.
Указав конкретную строку, где возникла логическая ошибка, Вы сами же не сможете разобраться, верно?
x= y\z

А вот если указать полный код
z=0
y=1
x= y\z

тогда шансы разобраться заметно возрастают.
Цитата
Алексей написал:
Переменной TEname присваивается строковое значение в самом начале main.
Вот еще одна причина ко которой нужен полный код, а не пара строк.
Как по Вашему до этой информации нам можно было бы разобраться?
Цитата
Алексей написал:
(Теперь то я перенес это в OnInit, но на исходное решение были свои соображения).

вообще, использовать заранее не инициализированные переменные является плохим тоном.
даже в документации об этом сказано (см описание OnInit)
Цитата
В данной функции пользователь имеет возможность инициализировать все необходимые переменные и библиотеки перед запуском основного потока main().

Цитата
Алексей написал:
Однако я столкнулся с необъяснимой ситуацией: в "Ошибки выполнения скрипта" светилось: "bad argument #1 to 'find' (string expected, got nil)", а скрипт прекрасно продолжал свою кипучую деятельность.
А может все проще и сообщение осталось от предыдущего запуска, до исправления ошибки?

Цитата
Алексей написал:
Из этого я и сделал предположение №2.
где из всего поста предположение №2? а то Вы их не нумеруете.
 
По поводу самой ошибки.
Цитата
Sergey Gorokhov написал:
вообще, использовать заранее не инициализированные переменные является плохим тоном.
даже в документации об этом сказано (см описание OnInit)
Полностью с Вами согласен, исправлюсь. И по моему, мы с Вами уже давно пришли в выводу, что ошибка возникала из-за того, что обработчик OnTransReply в редких случаях вызывался раньше, чем была инициализирована TEname. Теперь это делается в OnInit и об ошибке можно забыть. Спасибо.

Продолжил же я переписку, чтобы обратить внимание на то, что в документации к QLua я не нашел деталей реализации работы lua скрипта под Quikом, точнее вообще её неправильно понял. А именно:
Цитата
Sergey Gorokhov написал:
Какими правилами, Вы вообще о чем? Колбеки выполняются по событию.
Событие произошло до main вот и колбек сработал до main.
В чем вопрос, не понятно.
И я о том, что правил нет. Реализовать работу lua скрипта под Quikом можно было не менее, чем тремя способами:

Первый способ: сначала интерпретатор в основном потоке Quik проходит <Body>, получая адреса OnInit, main и обработчиков событий, затем вызывает OnInit(), затем, организует выделенный поток, запускает в нем main() и только потом настраивает вызовы описанных в скрипте обработчиков событий; (я изначально решил исходя из стр.6, что реализация такова; о стр. 6 - ниже)

Второй способ: сначала интерпретатор в основном потоке Quik проходит <Body>, получая адреса OnInit, main, и обработчиков событий, затем вызывает OnInit(), затем настраивает вызовы описанных в скрипте обработчиков событий, и только потом организует выделенный поток и запускает в нем main(); (теперь, по результатам переписки с Вами, полагаю, что в Quik реализована именно такая схема)

Третий способ: сначала интерпретатор в основном потоке Quik проходит <Body>, получая адреса main, и обработчиков событий (в т.ч. OnInit), затем настраивает вызовы описанных в скрипте обработчиков событий (в т.ч. OnInit), генерирует событие для вызова обработчика OnInit, и только потом организует выделенный поток и запускает в нем main(). То же возможный вариант для реализации, хотя в нем, очевидно, может случится так, что обработка прочих событий может начаться до OnInit().

И в документации к QLua я не увидел на этот счет четкой конкретики. Собственно поэтому и продолжил переписку.

Цитата
Sergey Gorokhov написал:
Цитата
Алексей написал:
И глядя на стр. 6 "Использование Lua в Рабочем месте QUIK.pdf"
На стр 6, данного документа рассказано как запустить скрипт Lua.
...
Что не так?
Вы, по ошибке, заглянули в "Интерпретатор языка Lua.pdf", а я ссылался на стр. 6 "Использование Lua в Рабочем месте QUIK.pdf". Приведенная там схема и натолкнула меня на мысль, что в Quik реализован первый способ работы lua скрипта.

Цитата
Sergey Gorokhov написал:
А может все проще и сообщение осталось от предыдущего запуска, до исправления ошибки?
Вообще-то, по моему, после перезапуска скрипта содержание ошибки от прошлого сеанса его работы должно стираться из окна "Доступные скрипты" раздел "Ошибки выполнения скрипта". Разве не так?

И столкнувшись с этим в работе моего скрипта (в версии с еще не исправленной ошибкой), я сделал предположение №2:
Цитата
Sergey Gorokhov написал:
где из всего поста предположение №2? а то Вы их не нумеруете.
Предположение №2 из #10-го поста:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.

Теперь уже, после столь детального обсуждения следует, наверное, уточнить:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до организации выделенного для main потока, не вырубают скрипт.
 
Цитата
Алексей написал:
Вы, по ошибке, заглянули в "Интерпретатор языка Lua.pdf", а я ссылался на стр. 6 "Использование Lua в Рабочем месте QUIK.pdf".
Да верно.
Цитата
Алексей написал:
Приведенная там схема и натолкнула меня на мысль, что в Quik реализован первый способ работы lua скрипта.
Приведенная там схема явно говорит о том что после OnInit() параллельно работают Main и колбеки. Параллельно означает что никакой очередности между ними нет.

Цитата
Алексей написал:
Вообще-то, по моему, после перезапуска скрипта содержание ошибки от прошлого сеанса его работы должно стираться из окна "Доступные скрипты" раздел "Ошибки выполнения скрипта". Разве не так?
А Вы проверили, действительно ли сообщение от предыдущего запуска?
Или это сообщение появилось после?

Цитата
Алексей написал:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до организации выделенного для main потока, не вырубают скрипт.

Кажется на это уже был дан вполне понятный ответ.
Цитата
Sergey Gorokhov написал:
ЦитатаАлексей написал:
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.
Так не должно быть.
 
Sergey Gorokhov
Добрый день,
Уточните относительно утверждения об очередности, что ее нет.
-----------------
Как я понимаю, так как колбеки работают в одном потоке, то будет очередность.
Полагаю, что их очередность либо определяется порядком появления их в скрипте,
либо заранее установленным порядком их обхода внутри терминала.
Что есть истина?
спасибо
 
Цитата
Николай Камынин написал:
Как я понимаю, так как колбеки работают в одном потоке, то будет очередность.

Николай, читайте внимательней.
Речь про колбеки в сравнении с main.
Между колбеками и main очередности нет.

Цитата
Николай Камынин написал:
Что есть истина?

колбеки выполняются в том порядке как они поступили в терминал QUIK.
Если один колбек затормозит, то накопится очередь, которая потом исполнится в том порядке в каком они поступили.
 
Цитата
Sergey Gorokhov написал:
Цитата
Алексей написал:
Вообще-то, по моему, после перезапуска скрипта содержание ошибки от прошлого сеанса его работы должно стираться из окна "Доступные скрипты" раздел "Ошибки выполнения скрипта". Разве не так?
А Вы проверили, действительно ли сообщение от предыдущего запуска?
Или это сообщение появилось после?
Кажется, я все никак не могу донести до Вас мысль, что сообщение горело в окне "Доступные скрипты" ВО ВРЕМЯ работы скрипта (зеленый треугольничек горит у наименования скрипта, скрипт явно функционирует, а внизу, в "Ошибки выполнения скрипта" - сообщение об ошибке.) Как во время работы скрипта в "Ошибки выполнения скрипта" может оставаться запись от предыдущего запуска скрипта?
По-моему - никак. Значит ошибка возникла после последнего старта скрипта, но не прервала его работу.
 
Цитата
Алексей написал:
По-моему - никак. Значит ошибка возникла после последнего старта скрипта, но не прервала его работу.

По идее да, никак. Однако ранее у нас были обращения от клиентов с тем что сообщение оставалось и это чинилось.
И как уже было сказано и еще раз повторим:

Цитата
Sergey Gorokhov написал:
Если требуется анализ, приведите полный код скрипта на котором возникает проблема и сообщите версию терминала QUIK
 
Цитата
Sergey Gorokhov написал:
Однако ранее у нас были обращения от клиентов с тем что сообщение оставалось и это чинилось.
Quik 7.14.1.7 - уже исправлено?

Скрипт, который, по идее, может воспроизвести такую ошибку может выглядеть как-то так:
Код
function OnInit()
  main_run = true
end

function main()
  TEname = "abc"
  while main_run do
    sleep(100)
  end
end

function OnTransReply(tab)
  if tab.brokerref and tab.brokerref:find(TEname) then
    message("Пришел мой OnTransReply")
  end
end

function OnStop()
  main_run = false
end
Скрипт должен быть запущен уже после соединения с сервером. С брокером должен идти обмен служебными транзакциями (в моей ситуации), или должен параллельно работать другой скрипт, отсылающий транзакции.
И нужно "подгадать" запуск скрипта так, чтобы пришел OnTransReply до старта main.
За все время работы моего скрипта (до исправления) ошибка было поймана лишь дважды, один раз скрипт вырубило, а второй случай - мы обсуждаем.
 
Алексей,
Вы сказали что ошибка проявилась после того как была исправлена проблема с TEname. А в приведенном коде она не исправлена.
 
Цитата
Sergey Gorokhov написал:
Цитата
Николай  Камынин   написал:
Как я понимаю, так как колбеки работают в одном потоке, то будет очередность.
Николай, читайте внимательней.
Речь про колбеки в сравнении с main.
Между колбеками и main очередности нет.
Цитата
Николай  Камынин   написал:
Что есть истина?
колбеки выполняются в том порядке как они поступили в терминал QUIK.
Если один колбек затормозит, то накопится очередь, которая потом исполнится в том порядке в каком они поступили.
Тогда поясните откуда колбеки поступают в терминал?
Спасибо.
 
Алексей, для выяснения, останавливает ли ошибка в callback скрипт, можно запустить
Код
function OnConnected()
   error("OnConnected")
end

function OnDisconnected()
   error("OnDisconnected")
end

local stop = false
function OnStop()
   stop = true
end

function main()
   while not stop do sleep(100) end
end
и перелогиниться.  Для моей версии 7.5.0.72 - нет, не останавливает.
 
Цитата
Sergey Gorokhov написал:
Алексей  ,
Вы сказали что ошибка проявилась после того как была исправлена проблема с TEname. А в приведенном коде она не исправлена.
Цитата
Алексей написал (в #21):
За все время работы моего скрипта (до исправления) ошибка было поймана лишь дважды, один раз скрипт вырубило, а второй случай - мы обсуждаем.
Я, видимо, ранее по ходу переписки недостаточно сакцентировал внимание на описании ситуации с возникновением второго варианта ошибки (когда ошибка высветилась, но скрипт продолжал работать). Эта, как и первая ошибка (просто вырубающая скрипт) была "поймана" на еще не исправленном скрипте. Т.е. обе ошибки были пойманы на скрипте, схема которого показана в #21 посте.
 
Цитата
Николай Камынин написал:
Тогда поясните откуда колбеки поступают в терминал?

Информация поступает с сервера, куда подключился терминал, это же очевидно.
 
Цитата
kroki написал:
и перелогиниться.  Для моей версии 7.5.0.72 - нет, не останавливает.

Версия очень старая, рекомендуется обновить до последней 7.14
 
Алексей,
На приведенном Вами коде, проблема не воспроизводится.
 
Цитата
Sergey Gorokhov написал:
Цитата
Николай  Камынин   написал:
Тогда поясните откуда колбеки поступают в терминал?
Информация поступает с сервера, куда подключился терминал, это же очевидно.
Конечно, информация поступает с сервера, но не колбеки.
Разницу улавливаете?
 
Цитата
Николай Камынин написал:
Тогда поясните откуда колбеки поступают в терминал?
Они не поступают в терминал, это терминал вызывает их.
 
колбеки вызываются из терминала
Это вызов функций, которые расположены в скриптах
Следовательно колбек приходит из терминала  в VMLua.
 
Цитата
Sergey Gorokhov написал:
Версия очень старая, рекомендуется обновить до последней 7.14
Sergey Gorokhov, я бы с радостью обновился, но как?  Из этой ветки я сделал вывод, что нет гарантий, что новая версия терминала будет работать со старой версией сервера у брокера.  Также на вашем сайте сказано, что:
Цитата
Дистрибутив может использоваться для подключения к серверам Технического центра ARQA Technologies. Для подключения к серверам брокеров необходимо использовать дистрибутив, предоставленный брокером.
Или это все устаревшая информация, и можно смело обновяться?  И есть ли где-нибудь пошаговая инструкция?  Ибо на само деле пробовал обновить, но не получилось...
 
kroki,
Новая версия терминала, может быть не совместима со старой версией сервера.
Обновление Вам следует запросить у Вашего брокера.
 
Цитата
Sergey Gorokhov написал:
Алексей  ,
На приведенном Вами коде, проблема не воспроизводится.
Естественно! Вероятность воспроизведения проблемы менее 0.1%. Я же указал, что ошибка за почти год эксплуатации скрипта возникла всего дважды.
Чтобы она возникла необходимо, чтобы OnTransReply пришел после OnInit, но до исполнения в main() TEname = "abc" (скрипт вырубается), или вообще до старта потока main (скрипт не вырубается).

Но сегодня я получил новое интересное событие: пришел OnCleanUp два раза подряд (подряд в том смысле, что между ними ни одного другого колбека). Мой скрипт действительно некорректно обрабатывает такой сценарий (исправлю) и в результате одна из функций, вызываемых из обработчика OnFuturesLimitChange входит в бесконечный рекурсивный вызов самой себя. В результате имеем:



Ошибка горит, а скрипт спокойно занят своими делами и успешно торгует.
 
Алексей,
Проблема изучается. Постараемся в ближайшее время дать ответ.
 
Алексей, Добрый день,
     
     
      Ошибка будет исправлена в одной из следующих версий программы
Страницы: 1
Читают тему
Наверх