Complete implementation of to-be-closed variables
diff --git a/ldo.c b/ldo.c
index f2d12f0..78e4c5c 100644
--- a/ldo.c
+++ b/ldo.c
@@ -676,12 +676,15 @@
       /* unroll continuation */
       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' */
-      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;
     }
-    else lua_assert(status == L->status);  /* normal end or yield */
   }
   *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
                                     : cast_int(L->top - (L->ci->func + 1));
diff --git a/testes/db.lua b/testes/db.lua
index 2feaaef..9da6821 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -734,19 +734,18 @@
 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)
 a, b = coroutine.resume(co, 3)
 t = {"'coroutine.yield'", "'f'", "in function <"}
-while coroutine.status(co) == "suspended" do
+repeat
   checktraceback(co, t)
   a, b = coroutine.resume(co)
   table.insert(t, 2, "'f'")   -- one more recursive call to 'f'
-end
-t[1] = "'error'"
+until b
 checktraceback(co, t)
 
 
diff --git a/testes/locals.lua b/testes/locals.lua
index d12c70a..f21fa2e 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -274,13 +274,38 @@
 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
-local co = coroutine.wrap(function()
+local co
+co = coroutine.wrap(function()
   local scoped x = function () os.exit(false) end    -- should not run
-   coroutine.yield()
+  co = nil
+  coroutine.yield()
 end)
-co()
-co = nil
+co()                 -- start coroutine
+assert(co == nil)    -- eventually it will be collected
 
 print('OK')