HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > ПРОГРАММИРОВАНИЕ > Общие вопросы программирования
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 13.06.2025, 17:56
Tema05
Познавший АНТИЧАТ
Регистрация: 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 калбека происходит какая-то ошибка (у меня искуственно при помощи
Код:
error("CRASH")
) то lua скрипт закономерно должен крашнуться. Где-то внутри вызова
Код:
gHandler()
выполнится lua_error (через sol) и ошибка дойдёт до lua. Но, проблема в том что в этом случаи управление потоку не будет возвращено и весь код после вызова неудачно выполненной lua функции
Код:
gHandler()
не отработает. Соответственно в представленном варианте
Код:
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 калбека крашили скрипт, а не игнорировались, но не ломали хук из которого они вызываются?
 
Ответить с цитированием

  #2  
Старый 13.06.2025, 18:08
вайега52
Флудер
Регистрация: 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 калбека происходит какая-то ошибка (у меня искуственно при помощи
Код:
error("CRASH")
) то lua скрипт закономерно должен крашнуться. Где-то внутри вызова
Код:
gHandler()
выполнится lua_error (через sol) и ошибка дойдёт до lua. Но, проблема в том что в этом случаи управление потоку не будет возвращено и весь код после вызова неудачно выполненной lua функции
Код:
gHandler()
не отработает. Соответственно в представленном варианте
Код:
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++ каллбека на хук
 
Ответить с цитированием

  #3  
Старый 13.06.2025, 18:30
вайега52
Флудер
Регистрация: 19.06.2022
Сообщений: 2,997
С нами: 2055431

Репутация: 3


По умолчанию

кстати, наверное тебе лучше использовать std::function, т.к. он более безопасный, но при этом, насколько помню, не оборачивает в pcall
 
Ответить с цитированием

  #4  
Старый 13.06.2025, 19:10
Tema05
Познавший АНТИЧАТ
Регистрация: 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)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.