issue #163 Couple of more tests for coroutines and deferred functions, plus some changes in ldo.c back-ported from Lua 5.4

memtest
Dibyendu Majumdar 4 years ago
parent e832dcc32f
commit b63005fd3f

@ -124,6 +124,7 @@ l_noret luaD_throw (lua_State *L, int errcode) {
}
else { /* thread has no error handler */
global_State *g = G(L);
errcode = luaF_close(L, L->stack, errcode); /* close all upvalues */
L->status = cast_byte(errcode); /* mark it as dead */
if (g->mainthread->errorJmp) { /* main thread has a handler? */
setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */
@ -767,19 +768,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, &nargs);
if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN;
else { /* continue running after recoverable errors */
while (errorstatus(status) && recover(L, status)) {
/* unroll continuation */
status = luaD_rawrunprotected(L, unroll, &status);
}
if (errorstatus(status)) { /* unrecoverable error? */
L->status = cast_byte(status); /* mark thread as 'dead' */
luaD_seterrorobj(L, status, L->top); /* push error message */
L->ci->top = L->top;
}
else lua_assert(status == L->status); /* normal end or yield */
/* continue running after recoverable errors */
while (errorstatus(status) && recover(L, status)) {
/* unroll continuation */
status = luaD_rawrunprotected(L, unroll, &status);
}
if (likely(!errorstatus(status)))
lua_assert(status == L->status); /* normal end or yield */
else { /* unrecoverable error */
L->status = cast_byte(status); /* mark thread as 'dead' */
luaD_seterrorobj(L, status, L->top); /* push error message */
L->ci->top = L->top;
}
L->nny = oldnny; /* restore 'nny' */
L->nCcalls--;

@ -424,4 +424,62 @@ do
print 'Test 10 OK'
end
-- a suspended coroutine should not close its variables when collected
do
function t()
local co
co = coroutine.wrap(function()
-- should not run
local x = func2close(function () os.exit(false) end)
defer getmetatable(x).__close(x) end
co = nil
coroutine.yield()
end)
co() -- start coroutine
assert(co == nil) -- eventually it will be collected
collectgarbage()
end
t()
compile(t)
t()
print 'Test 11 OK'
end
do
local function t()
-- error in a wrapped coroutine raising errors when closing a variable
local x = 0
local co = coroutine.wrap(function ()
local xx = func2close(function () x = x + 1; error("@YYY") end)
defer getmetatable(xx).__close(xx) end
local xv = func2close(function () x = x + 1; error("@XXX") end)
defer getmetatable(xv).__close(xv) end
coroutine.yield(100)
error(200)
end)
assert(co() == 100); assert(x == 0)
local st, msg = pcall(co); assert(x == 2)
assert(not st and msg == 200) -- should get first error raised
local x = 0
local y = 0
co = coroutine.wrap(function ()
local xx = func2close(function () y = y + 1; error("YYY") end)
defer getmetatable(xx).__close(xx) end
local xv = func2close(function () x = x + 1; error("XXX") end)
defer getmetatable(xv).__close(xv) end
coroutine.yield(100)
return 200
end)
assert(co() == 100); assert(x == 0)
local st, msg = pcall(co)
assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
assert(x == 1 and y == 1)
end
t()
compile(t)
t()
print 'Test 12 OK'
end
print 'OK'

Loading…
Cancel
Save