Скрипт прекращает работу, а не должен

Страницы: 1
RSS
Скрипт прекращает работу, а не должен, Скрипт прекращает работу по непонятной причине, как ее выявить?
 
Давно использую скрипт, который работает без ограничения по времени (ночью комп не выключается, утром он обновляет настройки и продолжает работу - очень удобно). В теле main он "бегает" по циклу с определенной паузой.
В последнее время он стал самостоятельно спонтанно выключаться по непонятной причине. При этом логи показывают что функция OnStop не запускается, также в окне "Доступные скрипты" нет указания на какую либо ошибку работы скрипта. Соответствующее окно сообщений пусто. Единственная обнаруженная закономерность - работа прекращается после успешного выполнения транзакции по удалению заявки... (это частое действие и в большинстве случаев оно завершается без проблем...)
Как в такой ситуации определить причину неожиданной остановки скрипта?
 
Цитата
Иван Ру написал:
Как в такой ситуации определить причину неожиданной остановки скрипта?

Добавить в скрипт логирование всего, и по факту остановки смотреть что было последним.
 
Sergey Gorokhov, скажите: я верно понимаю, что скрипт останавливается только в 2-х случаях:
1) Либо произошел корректный выход из main() -> тогда в окне скриптов не будет ошибки (и других сообщений)
2) Либо произошла какая-то (любая) ошибка  -> тогда в окне скриптов гарантированно будет отображена ошибка

Верно? других вариантов нет? Точно нет?

Если так, то Иван Ру будет достаточно добавить логирование условия выхода из цикла main() и всё станет понятно.
 
Цитата
swerg написал:
2) Либо произошла какая-то (любая) ошибка  -> тогда в окне скриптов гарантированно будет отображена ошибкаВерно? других вариантов нет? Точно нет?
Одно время я очень долго бился над поиском одной ошибки, и вот где она была:

Если некорректная операция, например деление на ноль, или например a = "b"..nil , совершается из функции main, то скрипт прекращает работу и выдает ошибку. Однако если такая же ошибка происходит из функции колбека (возможно не всех) но из тех, которые я использовал, например при изменении праметра инструмента, то скрипт просто останавливается, и ошибки никакой не выдает.

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

Для решения данной проблемы пришлось делать так, чтобы в функции колбека создавалось отложенное действие, а из main оно выполнялось. Тогда об ошибке сообщается
 
а последнее время меня здесь на форуме научили пользоваться pcall, чтобы даже в случае ошибки скрипт не прекращал работу, а выдавал ошибку, но продолжал. Тоже удобно.
 
Sergey Denegin,
Приведите пример кода.
И уточните версию терминала на которой воспроизводится проблема.
 
Цитата
Sergey Gorokhov написал:
Цитата
Иван Ру написал:
Как в такой ситуации определить причину неожиданной остановки скрипта?

Добавить в скрипт логирование всего, и по факту остановки смотреть что было последним.
У меня как раз такая реализация, но она прояснить проблему не позволяет... Судя по логам дело происходит так. Мой скрипт периодически удаляет заявки, затем проходит обработка для того чтобы учесть факт успешного/неуспешного удаления заявки. Все это в цикле с частотой около 50 миллисекунд. Остановка происходит обычно так - происходит успешное удаление заявки, в OnTransReply происходит обработка данных + специальная функция успешно обрабатывает /учитывает полученный результат и благополучно завершается. После этого скрипт работает доли секунды (прокручивается несколько циклов) и прекращает работу без сообщения об ошибке... OnStop не инициируется и не запускается, т.е. она ни при чем. В подавляющем большинстве случаев при наступления события (успешная транзакция по удалению заявки) никакой остановки не происходит, все работает штатно.
Ошибка наблюдается на терминалах версии 8.5
Код:


function fProcessReply (reply, place, clos, sec_code, pos, order_num, trans_id, Price) -- reply - отклик по транзакции, place -- на размещение TRUE, clos - закрытие позиции TRUE, sec_code, pos - позиция ОБЪЕКТ, order_num - номер заявки, trans_id - номер транзакции, Price - цена
-- обработка ошибок
if clos == nil then clos = pos.temp ; end
local dir = 1 -- направление сделки
if pos.dir == "S" then dir = -1; end -- корректируем его при необходимости
local result = ""
writeLog('fProcessReply'..";".."Try to process"..";"..sec_code..";"..tostring(place)..";".."order_num"..";"..tostring(order_num)..";".."trans_id"..";"..tostring(trans_id))
if reply ~= '' then  -- ОШИБКА (Это верно и для заявок на размещение и для заявок на удаление, значит необходимо оставить неизменным прежний статус заявки !!!!
result =  false ;
writeLog('fProcessReply'..";".."Error")
fRejectedOrderCase (sec_code, pos) -- запуск функции по обработке ошибочной транзакции !!! перепроверить
else -- УСПЕШНАЯ ОТПРАВКА (ответное сообщение нулевое)
result = true
-- Формируем базовые переменные
local SubDir = 0 -- поднаправление (размещение / закрытие)
local dirQty = 0 -- изменение лотов с учетом направления
local lotSize = pos.lotSize -- объем заявки в лотах (для заявки на удаления - остаток в лотах)
if pos.executedLots then lotSize = lotSize - pos.executedLots ; end -- корректируем с учетом остатка
-- Записываем общие (для заявок на размещение и удаление) флаги
pos.trans_id = trans_id; -- записываем номер ордера (uniq_trans_id - далее userId) в соответствующее поле позиции - это будет нужно для последующего поиска сделки
pos.placed = place
writeLog('fProcessReply'..";".."Placed flag"..";"..sec_code..";"..tostring(place))

if place == true then
----------- если заявка на РАЗМЕЩЕНИЕ -------------------------------------
writeLog('fProcessReply'..";".."Place order  success")
SubDir = 1
pos.PricePlaced = Price; -- записываем цену заявки
pos.posixOrig = tpCurTime -- записываем текущее время сделки
-- заявки на закрытие
if temp == true then  -- блокирование снятой временной позиции на закрытие
-- writeLog('fProcessReply'..";".."Block pose after killed"..";"..sec_code..";".."index"..";"..tostring(pos.index), true)
else -- размещена постоянная позиция на ВХОД
-- устанавливаем верхнюю и нижнюю границы для позиции на вход
local dopuskForPos = pos.dopusk
local dopuskHigh = 1 + pos.dopusk/100
local dopuskLow = 1 - pos.dopusk/100
pos.lowP = pos.basePrice * dopuskLow -- Базовая цена (оффер или бид) умножается на верхний коэффициент (верхний допуск)
pos.highP = pos.basePrice * dopuskHigh
writeLog ('fProcessReply'..";".."Define price limits"..";"..sec_code..";".."Price"..";"..tostring(Price)..";".."lowP"..";"..tostring(pos.lowP)..";".."highP"..";"..tostring(pos.highP), true)
end
----------- если заявка на УДАЛЕНИЕ ----------------------------------
else
writeLog('fProcessReply'..";".."Delet order success")
SubDir = -1;
-- Обнуляем ключевые параметры
pos.PricePlaced = 0; -- записываем цену заявки
pos.donttuch = curPosixTime + IdleTimeAfterKill
writeLog('fProcessReply'..";".."Change qty for killord"..";"..sec_code..";".."pos.lotSize"..";"..tostring(pos.lotSize)..";".."pos.executedLots"..";"..tostring(pos.executedLots), true)
checkOrder, dirCheck, balanceQty = fFindOrderAndCheckDirBalance (order_num) -- ищем заявку в таблице заявок
if checkOrder == true then -- если удалось найти заявку в общем списке заявок
lotSize = balanceQty
dir = dirCheck
writeLog('fProcessReply'..";".."Rechange qty for killord"..";"..sec_code..";".."balanceQty"..";"..tostring(balanceQty)..";".."dirCheck"..";"..tostring(dirCheck), true)
end  -- если удалось найти заявку в общем списке заявок
--Заявка на закрытие
if temp == true then  -- блокирование снятой временной позиции на закрытие
pos.block = true
writeLog('fProcessReply'..";".."Block pose after killed"..";"..sec_code..";".."index"..";"..tostring(pos.index), true)
else
pos.basePrice = 0 ;
pos.lowP = 0 -- Базовая цена (оффер или бид) умножается на верхний коэффициент (верхний допуск)
pos.highP = 0
end -- удаление снятой временной позиции на закрытие
end -- если заявка на РАЗМЕЩЕНИЕ
-- Корректировка баланса
dirQty = SubDir * lotSize * dir
writeLog('fProcessReply'..";".."Lots to balance"..";"..sec_code..";".."dir"..";"..tostring(dir)..";".."SubDir"..";"..tostring(SubDir)..";".."dirQty"..";"..tostring(dirQty), true)
if dir == 1 then -- если заявка на ПОКУПКУ
tShares [sec_code]['PlacedL'] = tShares [sec_code]['PlacedL'] + dirQty
else -- если заявка на ПРОДАЖУ
tShares [sec_code]['PlacedS'] = tShares [sec_code]['PlacedS'] - dirQty
end -- если заявка на покупку
if pos.temp == false then -- если заявка на ВХОД
tShares [sec_code]['placedEnter'] = tShares [sec_code]['placedEnter'] + dirQty
else -- если заявка на ЗАКРЫТИЕ (temp = true, "C")
tShares [sec_code]['placedClose'] = tShares [sec_code]['placedClose'] + dirQty
end -- если заявка на вход
writeLog('fProcessReply'..";".."Change Balance"..";"..sec_code..";".."dirQty"..";"..tostring(dirQty)..";".."placedEnter"..";"..tostring(tShares [sec_code]['placedEnter'])..";".."placedClose"..";"..tostring(tShares [sec_code]['placedClose'])..";".."PlacedL"..";"..tostring(tShares [sec_code]['PlacedL'])..";".."PlacedS"..";"..tostring(tShares [sec_code]['PlacedS']), true)
end
writeLog('fProcessReply()'..";"..tostring(result), true)
-- return result
end
 
Цитата
swerg написал:
  Sergey Gorokhov   , скажите: я верно понимаю, что скрипт останавливается только в 2-х случаях:
1) Либо произошел корректный выход из main() -> тогда в окне скриптов не будет ошибки (и других сообщений)
2) Либо произошла какая-то (любая) ошибка  -> тогда в окне скриптов гарантированно будет отображена ошибка

Верно? других вариантов нет? Точно нет?

Если так, то    Иван Ру      будет достаточно добавить логирование условия выхода из цикла main() и всё станет понятно.
Добрый день! Я стараюсь придерживаться этого принципа - логгировать все...
1. Нет в логике скрипта возможности выхода из main, только остановка вручную. Скрипт должен после запуска крутиться бесконечно - и крутился, неделями. Плюс есть логгирование, которое фиксирует такой выход...
Скрипт обрывается обычно в периоды частого выставления заявок, например, в начале сессии. Может, судя по логгированию, останавливаться в разных местах выполнения. Обычно это дополнительные функции по обработке заявок - стандартная Ontrasreply или функция написанная мной. Но четкой закономерности проявления ошибки нет.
2. В том и проблема, что никакого сообщения об ошибке нет... Если бы ошибка отображалась, было бы просто...
 
Иван Ру,
По присланной части кода разобраться не представляется возможным, думаю Вы сами это понимаете.
если хотите чтобы Вам помогли пришлите весь код.

Скрипт может остановиться в трех случаях
либо его остановили вручную
либо был выход из main
либо произошла ошибка.

Всё никаких других вариантов нет и быть не может и это совершенно точно.
Без полной версии кода, очевидно что мы не сможем проверить ни один из пунктов.
 
Цитата
Sergey Gorokhov написал:
Иван Ру,
По присланной части кода разобраться не представляется возможным, думаю Вы сами это понимаете.
если хотите чтобы Вам помогли пришлите весь код.

Скрипт может остановиться в трех случаях
либо его остановили вручную
либо был выход из main
либо произошла ошибка.

Всё никаких других вариантов нет и быть не может и это совершенно точно.
Без полной версии кода, очевидно что мы не сможем проверить ни один из пунктов.
Тогда вопрос: возможен ли такой вариант, что при остановке скрипта в результате ошибки никакое сообщение об ошибке  (в окне "Доступные скрипты" в поле "Ошибки выполнения скрипта") не выводится. Или ошибка исполнения всегда сопровождается соответствующим сообщением?

П.С. Код на 2600 строк, в нем непросто разобраться.
 
Цитата
Иван Ру написал:
Тогда вопрос: возможен ли такой вариант, что при остановке скрипта в результате ошибки никакое сообщение об ошибке  (в окне "Доступные скрипты" в поле "Ошибки выполнения скрипта") не выводится. Или ошибка исполнения всегда сопровождается соответствующим сообщением?
Нет.
Цитата
Иван Ру написал:
П.С. Код на 2600 строк, в нем непросто разобраться.

тогда без шансов.
 
Цитата
Sergey Gorokhov написал:
Цитата
Иван Ру написал:
Тогда вопрос: возможен ли такой вариант, что при остановке скрипта в результате ошибки никакое сообщение об ошибке  (в окне "Доступные скрипты" в поле "Ошибки выполнения скрипта") не выводится. Или ошибка исполнения всегда сопровождается соответствующим сообщением?
Нет.
Цитата
Иван Ру написал:
П.С. Код на 2600 строк, в нем непросто разобраться.

тогда без шансов.
Можете посоветовать внешние отладчики или другие методы позволяющие выявить место ошибки в скриптах в случаях, когда никакого сообщения о ней не приходит?
 
Отладчик Вам не поможет, если ошибка спонтанная, т.е. зависящая от данных. Допустим индексация значения nil, ожидая table.

В этом случае Вам проще обернуть критические функции в pcall, перехваченные ошибки записывать в лог. При этом надо обязательно добавить assert на входяшие данные.
Если ожидаете таблицу, проверьте что она и пришла. Ждете строку, проверьте, что она есть.
Тогда исключение по таким проверкам Вам и дать искомую ошибку.
 
Цитата
Nikolay написал:
Отладчик Вам не поможет, если ошибка спонтанная, т.е. зависящая от данных. Допустим индексация значения nil, ожидая table.

В этом случае Вам проще обернуть критические функции в pcall, перехваченные ошибки записывать в лог. При этом надо обязательно добавить assert на входяшие данные.
Если ожидаете таблицу, проверьте что она и пришла. Ждете строку, проверьте, что она есть.
Тогда исключение по таким проверкам Вам и дать искомую ошибку.
На данном этапе проблема в том, чтобы понять в каком месте ошибка, т.к. сообщения нет, а код очень велик... Если бы проблема была в неверном типе данных, сообщение об ошибке должно было бы приходить, насколько я понимаю...
 
Как вариант, где-то в цикле main используется return
Иван Ру, ваш вопрос звучит примерно так: "Угадайте, что в чёрном ящике"? Вряд ли кто-то сможет помочь.
 
Цитата
Старатель написал:
Как вариант, где-то в цикле main используется return
Иван Ру, ваш вопрос звучит примерно так: "Угадайте, что в чёрном ящике"? Вряд ли кто-то сможет помочь.
Речь об инструментах устранения ошибок, не о том, чтобы это кто-то сделал за меня. Хотя за подсказки тоже благодарен. Вот был уверен что return у меня в цикле нет, но после вашего замечания решил перепроверить и один таки нашел...
Страницы: 1
Читают тему (гостей: 1)
Наверх