aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-22 14:55:51 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-22 14:55:51 -0300
commitc90176f96924ee7d207501b32f216925773d3bdb (patch)
tree234f3aefb0617dd7e3d1ff5faf32f9fbdf96c2d7
parent3c7dc52909ce0688bdb20cacaf686413a79aaf48 (diff)
downloadlua-c90176f96924ee7d207501b32f216925773d3bdb.tar.gz
lua-c90176f96924ee7d207501b32f216925773d3bdb.tar.bz2
lua-c90176f96924ee7d207501b32f216925773d3bdb.zip
Complete implementation of to-be-closed variables
-rw-r--r--ldo.c9
-rw-r--r--testes/db.lua9
-rw-r--r--testes/locals.lua33
3 files changed, 39 insertions, 12 deletions
diff --git a/ldo.c b/ldo.c
index f2d12f04..78e4c5c3 100644
--- a/ldo.c
+++ b/ldo.c
@@ -676,12 +676,15 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
676 /* unroll continuation */ 676 /* unroll continuation */
677 status = luaD_rawrunprotected(L, unroll, &status); 677 status = luaD_rawrunprotected(L, unroll, &status);
678 } 678 }
679 if (unlikely(errorstatus(status))) { /* unrecoverable error? */ 679 if (likely(!errorstatus(status)))
680 lua_assert(status == L->status); /* normal end or yield */
681 else { /* unrecoverable error */
682 status = luaF_close(L, L->stack, status); /* close all upvalues */
680 L->status = cast_byte(status); /* mark thread as 'dead' */ 683 L->status = cast_byte(status); /* mark thread as 'dead' */
681 luaD_seterrorobj(L, status, L->top); /* push error message */ 684 luaD_seterrorobj(L, status, L->stack + 1); /* push error message */
685 L->ci = &L->base_ci; /* back to the original C level */
682 L->ci->top = L->top; 686 L->ci->top = L->top;
683 } 687 }
684 else lua_assert(status == L->status); /* normal end or yield */
685 } 688 }
686 *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield 689 *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
687 : cast_int(L->top - (L->ci->func + 1)); 690 : cast_int(L->top - (L->ci->func + 1));
diff --git a/testes/db.lua b/testes/db.lua
index 2feaaef1..9da68210 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -734,19 +734,18 @@ a, b = coroutine.resume(co, 100)
734assert(a and b == 30) 734assert(a and b == 30)
735 735
736 736
737-- check traceback of suspended (or dead with error) coroutines 737-- check traceback of suspended coroutines
738 738
739function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end 739function f(i) coroutine.yield(i == 0); f(i - 1) end
740 740
741co = coroutine.create(function (x) f(x) end) 741co = coroutine.create(function (x) f(x) end)
742a, b = coroutine.resume(co, 3) 742a, b = coroutine.resume(co, 3)
743t = {"'coroutine.yield'", "'f'", "in function <"} 743t = {"'coroutine.yield'", "'f'", "in function <"}
744while coroutine.status(co) == "suspended" do 744repeat
745 checktraceback(co, t) 745 checktraceback(co, t)
746 a, b = coroutine.resume(co) 746 a, b = coroutine.resume(co)
747 table.insert(t, 2, "'f'") -- one more recursive call to 'f' 747 table.insert(t, 2, "'f'") -- one more recursive call to 'f'
748end 748until b
749t[1] = "'error'"
750checktraceback(co, t) 749checktraceback(co, t)
751 750
752 751
diff --git a/testes/locals.lua b/testes/locals.lua
index d12c70a0..f21fa2ec 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -274,13 +274,38 @@ if rawget(_G, "T") then
274end 274end
275 275
276 276
277-- to-be-closed variables in coroutines
278do
279 -- an error in a coroutine closes variables
280 local x = false
281 local y = false
282 local co = coroutine.create(function ()
283 local scoped xv = function () x = true end
284 do
285 local scoped yv = function () y = true end
286 coroutine.yield(100) -- yield doesn't close variable
287 end
288 coroutine.yield(200) -- yield doesn't close variable
289 error(23) -- error does
290 end)
291
292 local a, b = coroutine.resume(co)
293 assert(a and b == 100 and not x and not y)
294 a, b = coroutine.resume(co)
295 assert(a and b == 200 and not x and y)
296 a, b = coroutine.resume(co)
297 assert(not a and b == 23 and x and y)
298end
299
277-- a suspended coroutine should not close its variables when collected 300-- a suspended coroutine should not close its variables when collected
278local co = coroutine.wrap(function() 301local co
302co = coroutine.wrap(function()
279 local scoped x = function () os.exit(false) end -- should not run 303 local scoped x = function () os.exit(false) end -- should not run
280 coroutine.yield() 304 co = nil
305 coroutine.yield()
281end) 306end)
282co() 307co() -- start coroutine
283co = nil 308assert(co == nil) -- eventually it will be collected
284 309
285print('OK') 310print('OK')
286 311