Контекст: луа-скрипт загружает длл, все остальное делается в длл через луа-си интерфейс. В том числе создаются луа-объекты с метатаблицами и обработчиками сборки мусора (финализаторами). Наблюдаю два случая.
1. Где-то в main() вызывается lua_error(). Все вообще здорово, main() завершается, отрабатывают финализаторы для созданных луа-объектов, длл выгружается, в окне квика с луа-скриптами выводится описание ошибки.
2. Вызываем lua_error() в OnInit(). Скрипт также мгновенно останавливается, в окне квика с луа-скриптами появляется описание ошибки, дополнительно выводится окно сообщений с тем же описанием. Но вот внутри длл происходит адъ и израиль. Финализаторы луа-объектов не вызываются, длл остается загруженной в квик. Дальше возможны варианты:
2.1. Если закрыть квик, длл выгружается средствами ос, естественно, ни о каких финализаторах из луа речь уже не идет.
2.2. Если повторно запустить этот же скрипт, "зависшие" объекты из предыдущего экземпляра финализируются, отрабатывает вся последовательность очистки, как в случае с ошибкой в main(). Но, естественно, новый экземпляр скрипта остается "недобитым".
2.3. Если запустить какой-нибудь другой скрипт, на "недобитый" скрипт это никак не влияет.
Выводы:
1. На текущем этапе допускать lua_error() в OnInit() и, возможно, в каких-то еще колбеках (не проверял еще) не представляется возможным без сочинения костылей для принудительной очистки в случае ошибки.
2. Разработчикам квика просьба посмотреть, что можно "дернуть" после ошибки в OnInit(), чтобы скрипт был "добит" как положено. Думается, достаточно будет гарбидж коллектор попросить собрать мусор в контексте убитого скрипта.
Пользователь
Сообщений: Регистрация: 21.08.2015
29.07.2019 04:23:22
Дополню. Проблема воспроизводится безо всяких длл следующим скриптом
Код
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, установив свой колбек и затем из него вызвав стандартный. Но это не работает, квик, похоже, вообще до паники не доходит, а сваливает скрипт где-то раньше своим особенным путем.
Как говорится, какие будут предложения? Вариант "будет исправлено когда-нибудь" тоже хорош, но нам надо работать сегодня с, хайли лайкли, позавчерашним квиком. Если что, опыты на восьмой версии проводились.
Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
QUIK clients support
Пользователь
Сообщений: Регистрация: 21.08.2015
29.07.2019 18:44:05
Еще со своей стороны могу добавить.
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). Не работает. Значит, объект еще не отмечен мусорным, его кто-то держит. Дальше уже надо в кишки квика смотреть, так что мне остается перейти на сторону зрителей.
Пользователь
Сообщений: Регистрация: 29.12.2018
30.07.2019 10:03:02
Здравствуйте! Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Обнаруженная вами проблема будет исправлена в одной из очередных версий программы. Приносим извинения за причиненные неудобства.
В качестве временного решения рекомендуем построить код иным образом, чтобы обойти эту проблему.
QUIK clients support
Пользователь
Сообщений: Регистрация: 21.08.2015
02.08.2019 13:04:54
Цитата
Alexander Kopyatkevich написал: В качестве временного решения рекомендуем построить код иным образом, чтобы обойти эту проблему.
Да, начал переписывать практически сразу, т.к. шансы на серебряную пулю были мизерные, да и хачить квик не хочется. Жаль, конечно, красивую архитектуру, try-catch -> lua_error и квик нас сам выгрузит. К сожалению, "иным образом" -- это сильно больше кода, но кому легко.
Для товарищей в теме замечу, что в таком режиме строго try-catch-(lock-custom_unload) в колбеках и cpcall -> throw во всех случаях, когда вызывается луа, единственное послабление - когда луа-функция точно не кидает ошибок, даже out of memory. Плюс можно местами извернуться, некоторые (в общем небезопасные) луа-функции ошибок не кидают при определенных условиях, например, lua_tostring не кидает, если не происходит приведения типа. Только что придется доку держать все время открытой и на каждый вызов лезть проверять, оборачивать его или обошлось, что, конечно, довольно-таки жесть.
Пользователь
Сообщений: Регистрация: 21.08.2015
21.03.2020 00:29:04
Определенно, некоторые работы были проведены. Теперь (8.3.2.4) и ошибка в мейне приводит к утечке. Скрипт:
Код
message("Before body")
t = newproxy(true)
mt = getmetatable(t)
mt["__gc"] = function(self) message("Garbage collector") end
function OnInit()
message("OnInit")
end
function main()
message("main")
error "Error in main()"
end
Ожидание: Before body - OnInit - main - Garbage collector. Если ошибку закомментировать, так и будет. Если оставить, то Реальность: Before body - OnInit - main - ??? Повторный запуск: Garbage collector - Before body - OnInit - main - ???
С нетерпением ждем новой версии луа, там ведь сразу уже нормально все будет, правда?
Ошибка описанная в данной ветке форума еще не исправлена, при выходе исправления здесь будет соответствующее уведомление.
Пользователь
Сообщений: Регистрация: 21.08.2015
25.03.2020 09:10:00
Цитата
Sergey Gorokhov написал: Ошибка описанная в данной ветке форума еще не исправлена, при выходе исправления здесь будет соответствующее уведомление.
Это понятно, но вот поведение-то изменилось волшебным образом, на это и хотел обратить внимание. Впрочем, до 8.5 уже недолго осталось, а там поглядим, как оно все будет.