 |

13.06.2025, 17:56
|
|
Познавший АНТИЧАТ
Регистрация: 05.10.2019
Сообщений: 1,649
С нами:
3477805
Репутация:
168
|
|
Вот упрощённый вариант частей моей dll-ки. Я ставлю хук на функцию игры и из lua устанавливаю калбек, который будет вызываться из оригинального C++ калбека. Всё отлично работает, но есть проблема с обработкой ошибок.
C++:
Код:
// установка lua калбека для вызова из хука
void
set_callback
(
sol
::
this_state ts
,
sol
::
unsafe_function func
)
{
gHandler
=
func
;
}
// вызывается при подключении библиотеки из lua через require
sol
::
table
open
(
sol
::
this_state ts
)
{
sol
::
state_view
lua
(
ts
)
;
installHook
(
)
;
module
.
set_function
(
"set_callback"
,
&
set_cb
)
;
return
module
;
}
extern
"C"
__declspec
(
dllexport
)
int
luaopen_lib
(
lua_State
*
L
)
{
return
(
sol
::
c_call
)
(
L
)
;
}
sol
::
unsafe_function gHandler
;
// тут будет хранится функция lua калбека
kthook
::
kthook_simple
mHookedFunc
;
// объект хука
// функция установки C++ хука
void
installHook
(
)
{
mHookedFunc
.
set_dest
(
0x123456
)
;
// адрес функции в игре на которую нужно поставить хук
mHookedFunc
.
set_cb
(
handleHookedFunc
)
;
// калбек, который будет срабатывать при вызове функции
mHookedFunc
.
install
(
)
// устанавливает хук
}
// калбек захуканной функции
bool
handleHookedFunc
(
const
kthook
::
kthook_simple
&
hook
,
void
*
ptr
)
{
gHandler
(
)
;
// вызов lua калбека. Если он пройдёт с ошибкой управление текущему потоку не вернётся и код ниже не выполнится
return
hook
.
call_trampoline
(
ptr
)
;
// трамплин на оригинальную функцию
}
Lua:
Код:
local
lib
=
require
'lib'
lib
.
set_callback
(
function
(
)
error
(
"LUA ERROR"
)
-- условно какая-то ошибка.
end
)
Если внутри lua калбека происходит какая-то ошибка (у меня искуственно при помощи
) то lua скрипт закономерно должен крашнуться. Где-то внутри вызова
выполнится lua_error (через sol) и ошибка дойдёт до lua. Но, проблема в том что в этом случаи управление потоку не будет возвращено и весь код после вызова неудачно выполненной lua функции
не отработает. Соответственно в представленном варианте
Код:
return hook.call_trampoline(ptr);
не выполнится, а это нарушает хука и игра разумеется умирает.
Я могу заменить sol::unsafe_function на sol:  rotected_function, тогда sol обернёт вызов lua функции в pcall, который отловит ошибку в lua калбеке и трамплин выполнится. Но, в этом случаи lua скрипт не крашнется. Ошибка была отловлена и "проглочена" при помощи pcall, в C++ мы её дальше никак не обрабатываем. А это мне не подходит, я хочу получать краш lua скрипта при ошибках в lua калбеке.
Если добавить проброс пойманной ошибки через throw это ни к чему хорошему не приведёт. Оригинальный C++ калбек хука handleHookedFunc выполняется непосредственно в том же потоке что и захуканная функция, т.е. в потоке игры, а это значит что исключение пробрасывается внутрь игры, это если не брать в расчёт что трамплин, который идёт позже также не вызывается. Игра также умирает.
C++:
Код:
bool
handleHookedFunc
(
const
kthook
::
kthook_simple
&
hook
,
void
*
ptr
)
{
sol
::
protected_function_result result
=
gHandler
(
)
;
// вызов lua калбека. Если он пройдёт с ошибкой управление текущему потоку не вернётся и код ниже не выполнится
if
(
!
result
.
valid
(
)
)
{
sol
::
error err
=
result
;
throw
err
;
}
return
hook
.
call_trampoline
(
ptr
)
;
// трамплин на оригинальную функцию
}
Теперь смотрим на moonloader. Там через addEventHandler можно установить калбека на всякие события, например "onReceivePacket" (событие отправки пакета данный на сервер). Эти события по сути также хуки каких-то функций/методов в игре. И внутри этих lua калбеков ошибки обрабатываются так как я хочу. Они крашат lua скрипт, при этом это никак не мешает работе игры, несмотря на то что вызов lua калбека идёт из хука.
Lua:
Код:
addEventHandler
(
'onReceivePacket'
,
function
(
id
,
bs
)
error
(
'LUA ERROR'
)
end
)
Как мне реализовать такую же обработку ошибок как в moonloader? Чтобы ошибки внутри lua калбека крашили скрипт, а не игнорировались, но не ломали хук из которого они вызываются?
|
|
|

13.06.2025, 18:08
|
|
Флудер
Регистрация: 19.06.2022
Сообщений: 2,997
С нами:
2055431
Репутация:
3
|
|
Сообщение от Tema05
Вот упрощённый вариант частей моей dll-ки. Я ставлю хук на функцию игры и из lua устанавливаю калбек, который будет вызываться из оригинального C++ калбека. Всё отлично работает, но есть проблема с обработкой ошибок.
C++:
Код:
// установка lua калбека для вызова из хука
void
set_callback
(
sol
::
this_state ts
,
sol
::
unsafe_function func
)
{
gHandler
=
func
;
}
// вызывается при подключении библиотеки из lua через require
sol
::
table
open
(
sol
::
this_state ts
)
{
sol
::
state_view
lua
(
ts
)
;
installHook
(
)
;
module
.
set_function
(
"set_callback"
,
&
set_cb
)
;
return
module
;
}
extern
"C"
__declspec
(
dllexport
)
int
luaopen_lib
(
lua_State
*
L
)
{
return
(
sol
::
c_call
)
(
L
)
;
}
sol
::
unsafe_function gHandler
;
// тут будет хранится функция lua калбека
kthook
::
kthook_simple
mHookedFunc
;
// объект хука
// функция установки C++ хука
void
installHook
(
)
{
mHookedFunc
.
set_dest
(
0x123456
)
;
// адрес функции в игре на которую нужно поставить хук
mHookedFunc
.
set_cb
(
handleHookedFunc
)
;
// калбек, который будет срабатывать при вызове функции
mHookedFunc
.
install
(
)
// устанавливает хук
}
// калбек захуканной функции
bool
handleHookedFunc
(
const
kthook
::
kthook_simple
&
hook
,
void
*
ptr
)
{
gHandler
(
)
;
// вызов lua калбека. Если он пройдёт с ошибкой управление текущему потоку не вернётся и код ниже не выполнится
return
hook
.
call_trampoline
(
ptr
)
;
// трамплин на оригинальную функцию
}
Lua:
Код:
local
lib
=
require
'lib'
lib
.
set_callback
(
function
(
)
error
(
"LUA ERROR"
)
-- условно какая-то ошибка.
end
)
Если внутри lua калбека происходит какая-то ошибка (у меня искуственно при помощи
) то lua скрипт закономерно должен крашнуться. Где-то внутри вызова
выполнится lua_error (через sol) и ошибка дойдёт до lua. Но, проблема в том что в этом случаи управление потоку не будет возвращено и весь код после вызова неудачно выполненной lua функции
не отработает. Соответственно в представленном варианте
Код:
return hook.call_trampoline(ptr);
не выполнится, а это нарушает хука и игра разумеется умирает.
Я могу заменить sol::unsafe_function на sol:  rotected_function, тогда sol обернёт вызов lua функции в pcall, который отловит ошибку в lua калбеке и трамплин выполнится. Но, в этом случаи lua скрипт не крашнется. Ошибка была отловлена и "проглочена" при помощи pcall, в C++ мы её дальше никак не обрабатываем. А это мне не подходит, я хочу получать краш lua скрипта при ошибках в lua калбеке.
Если добавить проброс пойманной ошибки через throw это ни к чему хорошему не приведёт. Оригинальный C++ калбек хука handleHookedFunc выполняется непосредственно в том же потоке что и захуканная функция, т.е. в потоке игры, а это значит что исключение пробрасывается внутрь игры, это если не брать в расчёт что трамплин, который идёт позже также не вызывается. Игра также умирает.
C++:
Код:
bool
handleHookedFunc
(
const
kthook
::
kthook_simple
&
hook
,
void
*
ptr
)
{
sol
::
protected_function_result result
=
gHandler
(
)
;
// вызов lua калбека. Если он пройдёт с ошибкой управление текущему потоку не вернётся и код ниже не выполнится
if
(
!
result
.
valid
(
)
)
{
sol
::
error err
=
result
;
throw
err
;
}
return
hook
.
call_trampoline
(
ptr
)
;
// трамплин на оригинальную функцию
}
Теперь смотрим на moonloader. Там через addEventHandler можно установить калбека на всякие события, например "onReceivePacket" (событие отправки пакета данный на сервер). Эти события по сути также хуки каких-то функций/методов в игре. И внутри этих lua калбеков ошибки обрабатываются так как я хочу. Они крашат lua скрипт, при этом это никак не мешает работе игры, несмотря на то что вызов lua калбека идёт из хука.
Lua:
Код:
addEventHandler
(
'onReceivePacket'
,
function
(
id
,
bs
)
error
(
'LUA ERROR'
)
end
)
Как мне реализовать такую же обработку ошибок как в moonloader? Чтобы ошибки внутри lua калбека крашили скрипт, а не игнорировались, но не ломали хук из которого они вызываются?
Я подозреваю, что обертка sol'а над луа функциями в случае ошибки кидает исключение, которое можешь попробовать поймать внутри C++ каллбека на хук
|
|
|

13.06.2025, 18:30
|
|
Флудер
Регистрация: 19.06.2022
Сообщений: 2,997
С нами:
2055431
Репутация:
3
|
|
кстати, наверное тебе лучше использовать std::function, т.к. он более безопасный, но при этом, насколько помню, не оборачивает в pcall
|
|
|

13.06.2025, 19:10
|
|
Познавший АНТИЧАТ
Регистрация: 05.10.2019
Сообщений: 1,649
С нами:
3477805
Репутация:
168
|
|
Сообщение от вайега52
Я подозреваю, что обертка sol'а над луа функциями в случае ошибки кидает исключение, которое можешь попробовать поймать внутри C++ каллбека на хук
Оно не кидает исключение. При ошибке с sol::unsafe_function там идёт longjmp из-за lua_error и управление уйдёт, даже если в try catch завернуть, а при sol:  rotected_function исключение не передаётся, только статус и текст ошибки если есть.
Сообщение от вайега52
кстати, наверное тебе лучше использовать std::function, т.к. он более безопасный, но при этом, насколько помню, не оборачивает в pcall
std::function (видимо ты имел ввиду sol::function) это и есть sol::unsafe_function или sol:  rotected_function в зависимости от наличия
Код:
#define SOL_NO_EXCEPTIONS 1
Я когда дебаггером пытался разобраться как оно в moonloader работает заметил, что иногда скрипт может крашнуться одновременно из-за нескольких ошибок. Что по идеи невозможно из-за однопоточного устройства lua или происходит из-за гонки потоков. Причём это не одно и то же событие и разные. Значит moonloader как-то в отдельных потоках или корутиных выполняет все эти события. Это скорее всего и позволяет обрабатывать ошибки на месте без потери управления потоком

|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|