Auxiliary buffer cannot close box with 'lua_remove'

To remove a to-be-closed variable from the stack in the C API a
function must use 'lua_settop' or 'lua_pop'. Previous implementation of
'luaL_pushresult' was not closing the box. (This commit also added
tests to check that box is being closed "as soon as possible".)
This commit is contained in:
Roberto Ierusalimschy
2018-11-26 14:16:17 -02:00
parent 7e63d3da02
commit 7696c6474f
3 changed files with 49 additions and 23 deletions

View File

@@ -242,6 +242,7 @@ do
assert(a == 1 and b == 2 and c == 3 and X == 20 and Y == 10 and d == nil)
end
do -- errors in __close
local log = {}
local function foo (err)
@@ -264,7 +265,9 @@ do -- errors in __close
and #log == 4)
end
if rawget(_G, "T") then
-- memory error inside closing function
local function foo ()
local *toclose y = function () T.alloccount() end
@@ -296,7 +299,7 @@ if rawget(_G, "T") then
local function test ()
local *toclose x = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
os.exit(false) -- should not run
assert(false) -- should not run
end
local _, msg = pcall(test)
@@ -326,33 +329,54 @@ if rawget(_G, "T") then
do -- testing 'toclose' in C string buffer
local s = string.rep("a", 10000)
collectgarbage()
local s = string.rep('a', 10000) -- large string
local m = T.totalmem()
collectgarbage("stop")
s = string.upper(s) -- allocate buffer + new string (10K each)
-- ensure buffer was deallocated
assert(T.totalmem() - m <= 11000)
collectgarbage("restart")
end
do -- now some tests for freeing buffer in case of errors
local lim = 10000 -- some size larger than the static buffer
local extra = 2000 -- some extra memory (for callinfo, etc.)
local s = string.rep("a", lim)
-- concat this table needs two buffer resizes (one for each 's')
local a = {s, s}
-- ensure proper initialization (stack space, metatable)
table.concat(a)
collectgarbage(); collectgarbage()
collectgarbage()
local m = T.totalmem()
m = T.totalmem()
collectgarbage("stop")
-- error in the first buffer allocation
T. totalmem(m + extra)
assert(not pcall(table.concat, a))
-- first buffer was not even allocated
assert(T.totalmem() - m <= extra)
-- error in the second buffer allocation
T.alloccount(3)
T. totalmem(m + lim + extra)
assert(not pcall(table.concat, a))
T.alloccount()
-- first buffer was released by 'toclose'
assert(T.totalmem() - m <= 5000)
assert(T.totalmem() - m <= extra)
-- error in creation of final string
T.alloccount(4)
T.totalmem(m + 2 * lim + extra)
assert(not pcall(table.concat, a))
T.alloccount()
-- second buffer was released by 'toclose'
assert(T.totalmem() - m <= 5000)
assert(T.totalmem() - m <= extra)
-- userdata, upvalue, buffer, buffer, string
T.alloccount(5)
assert(#table.concat(a) == 20000)
T.alloccount()
-- userdata, upvalue, buffer, buffer, final string
T.totalmem(m + 4*lim + extra)
assert(#table.concat(a) == 2*lim)
T.totalmem(0) -- remove memory limit
collectgarbage("restart")
print'+'
end