Wrap Lua pcall() and xpcall() to rethrow jailbreak exceptions
Jailbreak exceptions thrown in Wesnoth C++ code called under Lua pcall()
or xpcall() aren't handled immediately, allowing such exceptions to
potentially accumulate and cause a failed assertion.
For example, if a user tries to quit while Lua code is running under
pcall() or xpcall(), LUAI_TRY() stores and consumes the jailbreak
exception and the rest of the Lua code continues running. If the user
tries to quit again before the Lua code finishes, LUAI_TRY() attempts to
store another jailbreak exception, which causes wesnoth to abort.
This is a longstanding bug (since jailbreak exceptions were introduced
in commit d6512a0ef5
, version 1.9.5) that could affect World Conquest
and 16 of the 588 addons in 1.16 and 7 of the 141 in 1.17.
Fix this by wrapping pcall() and xpcall() to rethrow jailbreak
exceptions.
This commit is contained in:
parent
bcec952e1e
commit
83ad348037
2 changed files with 28 additions and 0 deletions
3
changelog_entries/system_lua.md
Normal file
3
changelog_entries/system_lua.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
### Miscellaneous and Bug Fixes
|
||||
* Fix delayed handling of Lua jailbreak exceptions (quit to menu or desktop, wesnothd connection errors, etc.) thrown during Lua `pcall()` and `xpcall()`, which could accumulate and cause wesnoth to abort. (PR #8234)
|
||||
* This bug has existed since jailbreak exceptions were introduced in version 1.9.5.
|
|
@ -302,6 +302,22 @@ static int intf_load(lua_State* L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for pcall and xpcall functions to rethrow jailbreak exceptions
|
||||
*/
|
||||
static int intf_pcall(lua_State *L)
|
||||
{
|
||||
lua_CFunction function = lua_tocfunction(L, lua_upvalueindex(1));
|
||||
assert(function); // The upvalue should be Lua's pcall or xpcall, or else something is very wrong.
|
||||
|
||||
int nRets = function(L);
|
||||
|
||||
// If a jailbreak exception was stored while running (x)pcall, rethrow it so Lua doesn't continue.
|
||||
lua_jailbreak_exception::rethrow();
|
||||
|
||||
return nRets;
|
||||
}
|
||||
|
||||
// The show lua console callback is similarly a method of lua kernel
|
||||
int lua_kernel_base::intf_show_lua_console(lua_State *L)
|
||||
{
|
||||
|
@ -833,6 +849,15 @@ lua_kernel_base::lua_kernel_base()
|
|||
lua_pushnil(L);
|
||||
lua_setglobal(L, "loadstring");
|
||||
|
||||
// Wrap the pcall and xpcall functions
|
||||
cmd_log_ << "Wrapping pcall and xpcall functions...\n";
|
||||
lua_getglobal(L, "pcall");
|
||||
lua_pushcclosure(L, intf_pcall, 1);
|
||||
lua_setglobal(L, "pcall");
|
||||
lua_getglobal(L, "xpcall");
|
||||
lua_pushcclosure(L, intf_pcall, 1);
|
||||
lua_setglobal(L, "xpcall");
|
||||
|
||||
cmd_log_ << "Initializing package repository...\n";
|
||||
// Create the package table.
|
||||
lua_getglobal(L, "wesnoth");
|
||||
|
|
Loading…
Add table
Reference in a new issue