abstract new xpcall wrapper into new API function safe_function

This commit is contained in:
Starbeamrainbowlabs 2024-10-14 19:25:53 +01:00
parent c01eb23488
commit 00b1aed1ff
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
3 changed files with 93 additions and 67 deletions

View file

@ -5,6 +5,7 @@
local wea_c = worldeditadditions_core local wea_c = worldeditadditions_core
local safe_region = dofile(wea_c.modpath.."/core/safe_region.lua") local safe_region = dofile(wea_c.modpath.."/core/safe_region.lua")
local human_size = wea_c.format.human_size local human_size = wea_c.format.human_size
local safe_function = wea_c.safe_function
-- TODO: Reimplement worldedit.player_notify(player_name, msg_text) -- TODO: Reimplement worldedit.player_notify(player_name, msg_text)
@ -34,56 +35,7 @@ local function run_command_stage2(player_name, func, parse_result, tbl_event)
wea_c:emit("post-execute", tbl_event) wea_c:emit("post-execute", tbl_event)
end end
local function send_error(player_name, cmdname, msg, stack_trace)
print("DEBUG:HAI SEND_ERROR")
local msg_compiled = table.concat({
"[//", cmdname, "] Error: ",
msg,
"\n",
"Please report this by opening an issue on GitHub! Bug report link (ctrl + click):\n",
"https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new?title=",
wea_c.format.escape(stack_trace:match("^[^\n]+")), -- extract 1st line & escape
"&body=",
wea_c.format.escape(table.concat({
[[## Describe the bug
What's the bug? Be clear and detailed but concise in our explanation. Don't forget to include any context, error messages, logs, and screenshots required to understand the issue if applicable.
## Reproduction steps
Steps to reproduce the behaviour:
1. Go to '...'
2. Click on '....'
3. Enter this command to '....'
4. See error
## System information (please complete the following information)
- **Operating system and version:** [e.g. iOS]
- **Minetest version:** [e.g. 5.8.0]
- **WorldEdit version:**
- **WorldEditAdditions version:**
Please add any other additional specific system information here too if you think it would help.
## Stack trace
- **Command name:** ]],
cmdname,
"\n",
"```\n",
stack_trace,
"```\n",
}, "")),
"\n",
"-------------------------------------\n",
"*** Stack trace ***\n",
stack_trace,
"\n",
"-------------------------------------\n"
}, "")
print("DEBUG:player_notify player_name", player_name, "msg_compiled", msg_compiled)
worldedit.player_notify(player_name, msg_compiled)
end
--- Command execution pipeline: before `paramtext` parsing but after validation. --- Command execution pipeline: before `paramtext` parsing but after validation.
-- --
@ -163,27 +115,12 @@ local function run_command(cmdname, options, player_name, paramtext)
wea_c:emit("pre-parse", tbl_event) wea_c:emit("pre-parse", tbl_event)
local parse_result
-- local did_error = false -- local did_error = false
local success_xpcall, error_message = xpcall(function() local success_safefn, success, parse_result = safe_function(options.parse, { paramtext }, player_name, "The command crashed when parsing the arguments.", cmdname)
parse_result = { options.parse(paramtext) } if not success_safefn then return false end -- error already sent to the player above
end, debug.traceback
--[[function(error_raw) print("DEBUG:run_command success_safefn", success_safefn, "success", success, "parse_result", parse_result)
did_error = true
error_message = error_raw
print("DEBUG:parse_result>>error", error_raw, "stack trace", debug.traceback())
end]]--
)
if not success_xpcall then
print("DEBUG:parse_result EXIT_DUE_TO_ERROR")
send_error(player_name, cmdname, "The command crashed when parsing the arguments.", error_message)
print("DEBUG:parse_result EXIT_DUE_TO_ERROR __final_call__")
return false
end
local success = table.remove(parse_result, 1)
if not success then if not success then
worldedit.player_notify(player_name, ("[//"..tostring(cmdname).."] "..tostring(parse_result[1])) or "Invalid usage (no further error message was provided by the command. This is probably a bug.)") worldedit.player_notify(player_name, ("[//"..tostring(cmdname).."] "..tostring(parse_result[1])) or "Invalid usage (no further error message was provided by the command. This is probably a bug.)")
return false return false

View file

@ -0,0 +1,88 @@
local weac = worldeditadditions_core
---
-- @module worldeditadditions_core
-- ███████ █████ ███████ ███████ ███████ ███ ██
-- ██ ██ ██ ██ ██ ██ ████ ██
-- ███████ ███████ █████ █████ █████ ██ ██ ██
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ███████ ██ ██ ██ ███████ ███████ ██ ██ ████
local function send_error(player_name, cmdname, msg, stack_trace)
print("DEBUG:HAI SEND_ERROR")
local msg_compiled = table.concat({
"[//", cmdname, "] Error: ",
msg,
"\n",
"Please report this by opening an issue on GitHub! Bug report link (ctrl + click):\n",
"https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new?title=",
weac.format.escape(stack_trace:match("^[^\n]+")), -- extract 1st line & escape
"&body=",
weac.format.escape(table.concat({
[[## Describe the bug
What's the bug? Be clear and detailed but concise in our explanation. Don't forget to include any context, error messages, logs, and screenshots required to understand the issue if applicable.
## Reproduction steps
Steps to reproduce the behaviour:
1. Go to '...'
2. Click on '....'
3. Enter this command to '....'
4. See error
## System information (please complete the following information)
- **Operating system and version:** [e.g. iOS]
- **Minetest version:** [e.g. 5.8.0]
- **WorldEdit version:**
- **WorldEditAdditions version:**
Please add any other additional specific system information here too if you think it would help.
## Stack trace
- **Command name:** ]],
cmdname,
"\n",
"```\n",
stack_trace,
"\n",
"```\n",
}, "")),
"\n",
"-------------------------------------\n",
"*** Stack trace ***\n",
stack_trace,
"\n",
"-------------------------------------\n"
}, "")
print("DEBUG:player_notify player_name", player_name, "msg_compiled", msg_compiled)
worldedit.player_notify(player_name, msg_compiled)
end
--- Calls the given function `fn` with the UNPACKED arguments from `args`, catching errors and sending the calling player a nice error message with a report link.
--
-- WARNING: Do NOT nest `safe_function()` calls!!!
-- @param fn function The function to call
-- @param args table The table of args to unpack and send to `fn` as arguments
-- @param string|nil player_name The name of the player affected. If nil then no message is sent to the player.
-- @param string error_msg The error message to send when `fn` inevitably crashes.
-- @param string|nil cmdname Optional. The name of the command being run.
-- @returns bool,any,... A success bool (true == success), and then if success == true the rest of the arguments are the (unpacked) return values from the function called.
function safe_function(fn, args, player_name, error_msg, cmdname)
local retvals
local success_xpcall, stack_trace = xpcall(function()
retvals = { fn(weac.table.unpack(args)) }
end, debug.traceback)
if not success_xpcall then
send_error(player_name, cmdname, error_msg, stack_trace)
return false
end
return true, weac.table.unpack(retvals)
end
return safe_function

View file

@ -86,6 +86,7 @@ dofile(wea_c.modpath.."/utils/player.lua") -- Player info functions
wea_c.setting_handler = dofile(wea_c.modpath.."/utils/setting_handler.lua") -- AFTER parser wea_c.setting_handler = dofile(wea_c.modpath.."/utils/setting_handler.lua") -- AFTER parser
wea_c.pos = dofile(modpath.."/core/pos.lua") -- AFTER EventEmitter wea_c.pos = dofile(modpath.."/core/pos.lua") -- AFTER EventEmitter
wea_c.safe_function = dofile(modpath.."/core/safe_function.lua")
wea_c.register_command = dofile(modpath.."/core/register_command.lua") wea_c.register_command = dofile(modpath.."/core/register_command.lua")
wea_c.command_exists = dofile(modpath.."/core/command_exists.lua") wea_c.command_exists = dofile(modpath.."/core/command_exists.lua")
wea_c.fetch_command_def = dofile(modpath.."/core/fetch_command_def.lua") wea_c.fetch_command_def = dofile(modpath.."/core/fetch_command_def.lua")