lua_error() в OnInit

Страницы: 1
RSS
lua_error() в OnInit, Неправильное поведение
 
Контекст: луа-скрипт загружает длл, все остальное делается в длл через луа-си интерфейс. В том числе создаются луа-объекты с метатаблицами и обработчиками сборки мусора (финализаторами). Наблюдаю два случая.

1. Где-то в main() вызывается lua_error(). Все вообще здорово, main() завершается, отрабатывают финализаторы для созданных луа-объектов, длл выгружается, в окне квика с луа-скриптами выводится описание ошибки.

2. Вызываем lua_error() в OnInit(). Скрипт также мгновенно останавливается, в окне квика с луа-скриптами появляется описание ошибки, дополнительно выводится окно сообщений с тем же описанием. Но вот внутри длл происходит адъ и израиль. Финализаторы луа-объектов не вызываются, длл остается загруженной в квик. Дальше возможны варианты:

2.1. Если закрыть квик, длл выгружается средствами ос, естественно, ни о каких финализаторах из луа речь уже не идет.

2.2. Если повторно запустить этот же скрипт, "зависшие" объекты из предыдущего экземпляра финализируются, отрабатывает вся последовательность очистки, как в случае с ошибкой в main(). Но, естественно, новый экземпляр скрипта остается "недобитым".

2.3. Если запустить какой-нибудь другой скрипт, на "недобитый" скрипт это никак не влияет.

Выводы:

1. На текущем этапе допускать lua_error() в OnInit() и, возможно, в каких-то еще колбеках (не проверял еще) не представляется возможным без сочинения костылей для принудительной очистки в случае ошибки.

2. Разработчикам квика просьба посмотреть, что можно "дернуть" после ошибки в OnInit(), чтобы скрипт был "добит" как положено. Думается, достаточно будет гарбидж коллектор попросить собрать мусор в контексте убитого скрипта.
 
Дополню. Проблема воспроизводится безо всяких длл следующим скриптом

Код
t = newproxy(true)
mt = getmetatable(t)
mt["__gc"] = function(self) message("Hi, I'm Garbage Collector") end

function OnInit()
   --error "Error in OnInit"
end

function main()
   error "Error in main()"
end

В приведенном виде после ошибки в main выводится сообщение гарбидж коллектора. Если, однако, раскомментировать генерацию ошибки в OnInit, сообщения от коллектора не будет.

Очевидным решением было воспользоваться lua_atpanic, установив свой колбек и затем из него вызвав стандартный. Но это не работает, квик, похоже, вообще до паники не доходит, а сваливает скрипт где-то раньше своим особенным путем.

Как говорится, какие будут предложения? Вариант "будет исправлено когда-нибудь" тоже хорош, но нам надо работать сегодня с, хайли лайкли, позавчерашним квиком. Если что, опыты на восьмой версии проводились.
 
Здравствуйте, Anton.

Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
QUIK clients support
 
Еще со своей стороны могу добавить.

1. Более наглядный вариант тестового скрипта

Код
sleep(1000)
message("Userdata object creation")
t = newproxy(true)
mt = getmetatable(t)
mt["__gc"] = function(self) message("Hi, I'm Garbage Collector") end

function OnInit()
   sleep(1000)
   error "Error in OnInit"
end

function main()
   error "Error in main()"
end
показывает, что при повторном запуске после ошибки мусор собирается сразу же, еще до пересоздания глобального объекта с финализатором. Что как бы намекает, что достаточно просто дать луа шанс доработать после ошибки, т.е. квику нужно после прибития скрипта выполнить какой-то (возможно, любой) луа-код в том же контексте. Однако,

2. Попытался проделать это, а именно запустил перед OnInit отдельный поток, который, если через секунду ничего не произойдет, будет дергать lua_gc(context_from_on_init, LUA_GCCOLLECT, 0). Не работает. Значит, объект еще не отмечен мусорным, его кто-то держит. Дальше уже надо в кишки квика смотреть, так что мне остается перейти на сторону зрителей.
 
Здравствуйте!
Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
QUIK clients support
 
Здравствуйте, Anton.

Обнаруженная вами проблема будет исправлена в одной из очередных версий программы.
Приносим извинения за причиненные неудобства.

В качестве временного решения рекомендуем построить код иным образом,  чтобы обойти эту проблему.
QUIK clients support
 
Цитата
Alexander Kopyatkevich написал:
В качестве временного решения рекомендуем построить код иным образом,  чтобы обойти эту проблему.
Да, начал переписывать практически сразу, т.к. шансы на серебряную пулю были мизерные, да и хачить квик не хочется. Жаль, конечно, красивую архитектуру, try-catch -> lua_error и квик нас сам выгрузит. К сожалению, "иным образом" -- это сильно больше кода, но кому легко.


Для товарищей в теме замечу, что в таком режиме строго try-catch-(lock-custom_unload) в колбеках и cpcall -> throw во всех случаях, когда вызывается луа, единственное послабление - когда луа-функция точно не кидает ошибок, даже out of memory. Плюс можно местами извернуться, некоторые (в общем небезопасные) луа-функции ошибок не кидают при определенных условиях, например, lua_tostring не кидает, если не происходит приведения типа. Только что придется доку держать все время открытой и на каждый вызов лезть проверять, оборачивать его или обошлось, что, конечно, довольно-таки жесть.
Страницы: 1
Читают тему (гостей: 1)
Наверх