Lua 5.4 <close> variable attribute and error propagation behavior
0 reputation · 24 Sept 2022, 01:14 UTC
0 reputation · 24 Sept 2022, 01:14 UTC
Lua 5.4 introduces the <close> variable attribute, which allows for automatic resource cleanup by invoking the __close metamethod when a variable exits its scope. This mechanism is intended to simplify resource release patterns that previously required manual pcall wrappers in Lua 5.3.
A critical consideration arises when a scope is exited due to an error rather than a normal return. Specifically, the interaction between an existing error in the main block and a potential error raised within the __close metamethod creates uncertainty regarding the final state of the execution and the number of times the cleanup logic is triggered.
When targeting environments that may use different Lua 5.4 builds or compatibility shims, the exact sequence of metamethod invocation during an error-driven scope exit remains a point of ambiguity.
__close metamethod execute exactly once if an error is raised within the block?__close metamethod itself raises an error during a scope exit already triggered by a previous error, which error takes precedence?33775 reputation · 24 Sept 2022, 12:03 UTC
<close> variable attribute provides deterministic resource cleanup. When a variable with this attribute goes out of scope, the __close metamethod is automatically invoked. This behavior remains consistent even during stack unwinding via errors.
Does the __close metamethod execute exactly once if an error is raised within the block?
Yes. The virtual machine ensures that the __close metamethod is called exactly once when the variable becomes unreachable. This holds true whether the scope is exited via a normal return, a break, or an error. The mechanism is designed to guarantee that resources are not leaked even if the execution flow fails unexpectedly.
If the __close metamethod itself raises an error during a scope exit already triggered by a previous error, which error takes precedence?
The original error takes precedence. If an error is already being propagated (the stack is currently unwinding) and the __close metamethod throws a new error, the new error is discarded. This prevents cleanup logic from masking the root cause of the failure, which is a critical design choice for robust error handling.
To verify this behavior in a Lua 5.4 environment, you can use the following test pattern:
local res = setmetatable({}, {
__close = function(v)
print("Cleanup running...")
-- To test error precedence, uncomment the line below:
-- error("Cleanup failed!")\n end
})
local success, err = pcall(function()
local x = res [<close>]
x = x
error("Main block error!")
end)
printf("Success: %s\n", tostring(success))
printf("Error: %s\n", tostring(err))
<close> attribute.__close metamethod is only triggered when the variable goes out of scope; reassessing the variable within the same scope will trigger the cleanup for the old value immediately.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.