mirror of https://github.com/rusefi/lua.git
Complete implementation of to-be-closed variables
This commit is contained in:
parent
3c7dc52909
commit
c90176f969
9
ldo.c
9
ldo.c
|
@ -676,12 +676,15 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
|
||||||
/* unroll continuation */
|
/* unroll continuation */
|
||||||
status = luaD_rawrunprotected(L, unroll, &status);
|
status = luaD_rawrunprotected(L, unroll, &status);
|
||||||
}
|
}
|
||||||
if (unlikely(errorstatus(status))) { /* unrecoverable error? */
|
if (likely(!errorstatus(status)))
|
||||||
|
lua_assert(status == L->status); /* normal end or yield */
|
||||||
|
else { /* unrecoverable error */
|
||||||
|
status = luaF_close(L, L->stack, status); /* close all upvalues */
|
||||||
L->status = cast_byte(status); /* mark thread as 'dead' */
|
L->status = cast_byte(status); /* mark thread as 'dead' */
|
||||||
luaD_seterrorobj(L, status, L->top); /* push error message */
|
luaD_seterrorobj(L, status, L->stack + 1); /* push error message */
|
||||||
|
L->ci = &L->base_ci; /* back to the original C level */
|
||||||
L->ci->top = L->top;
|
L->ci->top = L->top;
|
||||||
}
|
}
|
||||||
else lua_assert(status == L->status); /* normal end or yield */
|
|
||||||
}
|
}
|
||||||
*nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
|
*nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
|
||||||
: cast_int(L->top - (L->ci->func + 1));
|
: cast_int(L->top - (L->ci->func + 1));
|
||||||
|
|
|
@ -734,19 +734,18 @@ a, b = coroutine.resume(co, 100)
|
||||||
assert(a and b == 30)
|
assert(a and b == 30)
|
||||||
|
|
||||||
|
|
||||||
-- check traceback of suspended (or dead with error) coroutines
|
-- check traceback of suspended coroutines
|
||||||
|
|
||||||
function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
|
function f(i) coroutine.yield(i == 0); f(i - 1) end
|
||||||
|
|
||||||
co = coroutine.create(function (x) f(x) end)
|
co = coroutine.create(function (x) f(x) end)
|
||||||
a, b = coroutine.resume(co, 3)
|
a, b = coroutine.resume(co, 3)
|
||||||
t = {"'coroutine.yield'", "'f'", "in function <"}
|
t = {"'coroutine.yield'", "'f'", "in function <"}
|
||||||
while coroutine.status(co) == "suspended" do
|
repeat
|
||||||
checktraceback(co, t)
|
checktraceback(co, t)
|
||||||
a, b = coroutine.resume(co)
|
a, b = coroutine.resume(co)
|
||||||
table.insert(t, 2, "'f'") -- one more recursive call to 'f'
|
table.insert(t, 2, "'f'") -- one more recursive call to 'f'
|
||||||
end
|
until b
|
||||||
t[1] = "'error'"
|
|
||||||
checktraceback(co, t)
|
checktraceback(co, t)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -274,13 +274,38 @@ if rawget(_G, "T") then
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- to-be-closed variables in coroutines
|
||||||
|
do
|
||||||
|
-- an error in a coroutine closes variables
|
||||||
|
local x = false
|
||||||
|
local y = false
|
||||||
|
local co = coroutine.create(function ()
|
||||||
|
local scoped xv = function () x = true end
|
||||||
|
do
|
||||||
|
local scoped yv = function () y = true end
|
||||||
|
coroutine.yield(100) -- yield doesn't close variable
|
||||||
|
end
|
||||||
|
coroutine.yield(200) -- yield doesn't close variable
|
||||||
|
error(23) -- error does
|
||||||
|
end)
|
||||||
|
|
||||||
|
local a, b = coroutine.resume(co)
|
||||||
|
assert(a and b == 100 and not x and not y)
|
||||||
|
a, b = coroutine.resume(co)
|
||||||
|
assert(a and b == 200 and not x and y)
|
||||||
|
a, b = coroutine.resume(co)
|
||||||
|
assert(not a and b == 23 and x and y)
|
||||||
|
end
|
||||||
|
|
||||||
-- a suspended coroutine should not close its variables when collected
|
-- a suspended coroutine should not close its variables when collected
|
||||||
local co = coroutine.wrap(function()
|
local co
|
||||||
|
co = coroutine.wrap(function()
|
||||||
local scoped x = function () os.exit(false) end -- should not run
|
local scoped x = function () os.exit(false) end -- should not run
|
||||||
coroutine.yield()
|
co = nil
|
||||||
|
coroutine.yield()
|
||||||
end)
|
end)
|
||||||
co()
|
co() -- start coroutine
|
||||||
co = nil
|
assert(co == nil) -- eventually it will be collected
|
||||||
|
|
||||||
print('OK')
|
print('OK')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue