aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-18 11:22:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-18 11:22:42 -0300
commit409256b7849ec5ab3296cb0ab9eba3d65955d5ea (patch)
tree13d6327093e900cab0b23c4d09f344a281630c73
parentb17178b27a55bd5eeb51538bec935972fd58f1ea (diff)
downloadlua-409256b7849ec5ab3296cb0ab9eba3d65955d5ea.tar.gz
lua-409256b7849ec5ab3296cb0ab9eba3d65955d5ea.tar.bz2
lua-409256b7849ec5ab3296cb0ab9eba3d65955d5ea.zip
'coroutine.close'/'lua_resetthread' report original errors
Besides errors in closing methods, 'coroutine.close' and 'lua_resetthread' also consider the original error that stopped the thread, if any.
-rw-r--r--lstate.c8
-rw-r--r--manual/manual.of10
-rw-r--r--testes/coroutine.lua10
-rw-r--r--testes/cstack.lua4
-rw-r--r--testes/locals.lua23
5 files changed, 40 insertions, 15 deletions
diff --git a/lstate.c b/lstate.c
index 1596b51c..96187c66 100644
--- a/lstate.c
+++ b/lstate.c
@@ -323,14 +323,16 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
323 323
324int lua_resetthread (lua_State *L) { 324int lua_resetthread (lua_State *L) {
325 CallInfo *ci; 325 CallInfo *ci;
326 int status; 326 int status = L->status;
327 lua_lock(L); 327 lua_lock(L);
328 L->ci = ci = &L->base_ci; /* unwind CallInfo list */ 328 L->ci = ci = &L->base_ci; /* unwind CallInfo list */
329 setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ 329 setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */
330 ci->func = L->stack; 330 ci->func = L->stack;
331 ci->callstatus = CIST_C; 331 ci->callstatus = CIST_C;
332 status = luaF_close(L, L->stack, CLOSEPROTECT); 332 if (status == LUA_OK || status == LUA_YIELD)
333 if (status != CLOSEPROTECT) /* real errors? */ 333 status = CLOSEPROTECT; /* run closing methods in protected mode */
334 status = luaF_close(L, L->stack, status);
335 if (status != CLOSEPROTECT) /* errors? */
334 luaD_seterrorobj(L, status, L->stack + 1); 336 luaD_seterrorobj(L, status, L->stack + 1);
335 else { 337 else {
336 status = LUA_OK; 338 status = LUA_OK;
diff --git a/manual/manual.of b/manual/manual.of
index 771bace0..164e359a 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -4098,10 +4098,12 @@ and then pops the top element.
4098Resets a thread, cleaning its call stack and closing all pending 4098Resets a thread, cleaning its call stack and closing all pending
4099to-be-closed variables. 4099to-be-closed variables.
4100Returns a status code: 4100Returns a status code:
4101@Lid{LUA_OK} for no errors in closing methods, 4101@Lid{LUA_OK} for no errors in the thread
4102(either the original error that stopped the thread or
4103errors in closing methods),
4102or an error status otherwise. 4104or an error status otherwise.
4103In case of error, 4105In case of error,
4104leaves the error object on the top of the stack, 4106leaves the error object on the top of the stack.
4105 4107
4106} 4108}
4107 4109
@@ -6577,7 +6579,9 @@ that is,
6577closes all its pending to-be-closed variables 6579closes all its pending to-be-closed variables
6578and puts the coroutine in a dead state. 6580and puts the coroutine in a dead state.
6579The given coroutine must be dead or suspended. 6581The given coroutine must be dead or suspended.
6580In case of error closing some variable, 6582In case of error
6583(either the original error that stopped the coroutine or
6584errors in closing methods),
6581returns @false plus the error object; 6585returns @false plus the error object;
6582otherwise returns @true. 6586otherwise returns @true.
6583 6587
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 5b927151..aaf565fb 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -134,7 +134,8 @@ do
134 local co = coroutine.create(print) 134 local co = coroutine.create(print)
135 assert(coroutine.resume(co, "testing 'coroutine.close'")) 135 assert(coroutine.resume(co, "testing 'coroutine.close'"))
136 assert(coroutine.status(co) == "dead") 136 assert(coroutine.status(co) == "dead")
137 assert(coroutine.close(co)) 137 local st, msg = coroutine.close(co)
138 assert(st and msg == nil)
138 139
139 -- cannot close the running coroutine 140 -- cannot close the running coroutine
140 local st, msg = pcall(coroutine.close, coroutine.running()) 141 local st, msg = pcall(coroutine.close, coroutine.running())
@@ -151,6 +152,13 @@ do
151 -- to-be-closed variables in coroutines 152 -- to-be-closed variables in coroutines
152 local X 153 local X
153 154
155 -- closing a coroutine after an error
156 local co = coroutine.create(error)
157 local st, msg = coroutine.resume(co, 100)
158 assert(not st and msg == 100)
159 st, msg = coroutine.close(co)
160 assert(not st and msg == 100)
161
154 co = coroutine.create(function () 162 co = coroutine.create(function ()
155 local x <close> = func2close(function (self, err) 163 local x <close> = func2close(function (self, err)
156 assert(err == nil); X = false 164 assert(err == nil); X = false
diff --git a/testes/cstack.lua b/testes/cstack.lua
index 8ac48e89..7bd55063 100644
--- a/testes/cstack.lua
+++ b/testes/cstack.lua
@@ -135,14 +135,18 @@ if T then
135 local topB, sizeB -- top and size Before overflow 135 local topB, sizeB -- top and size Before overflow
136 local topA, sizeA -- top and size After overflow 136 local topA, sizeA -- top and size After overflow
137 topB, sizeB = T.stacklevel() 137 topB, sizeB = T.stacklevel()
138 collectgarbage("stop") -- __gc should not be called with a full stack
138 xpcall(f, err) 139 xpcall(f, err)
140 collectgarbage("restart")
139 topA, sizeA = T.stacklevel() 141 topA, sizeA = T.stacklevel()
140 -- sizes should be comparable 142 -- sizes should be comparable
141 assert(topA == topB and sizeA < sizeB * 2) 143 assert(topA == topB and sizeA < sizeB * 2)
142 print(string.format("maximum stack size: %d", stack1)) 144 print(string.format("maximum stack size: %d", stack1))
143 LIM = N -- will stop recursion at maximum level 145 LIM = N -- will stop recursion at maximum level
144 N = 0 -- to count again 146 N = 0 -- to count again
147 collectgarbage("stop") -- __gc should not be called with a full stack
145 f() 148 f()
149 collectgarbage("restart")
146 print"+" 150 print"+"
147end 151end
148 152
diff --git a/testes/locals.lua b/testes/locals.lua
index df44b86f..e2f6f35c 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -362,7 +362,7 @@ end
362 362
363local function checkwarn (msg) 363local function checkwarn (msg)
364 if T then 364 if T then
365 assert(string.find(_WARN, msg)) 365 assert(_WARN and string.find(_WARN, msg))
366 _WARN = false -- reset variable to check next warning 366 _WARN = false -- reset variable to check next warning
367 end 367 end
368end 368end
@@ -670,10 +670,13 @@ do
670 -- error in a wrapped coroutine raising errors when closing a variable 670 -- error in a wrapped coroutine raising errors when closing a variable
671 local x = 0 671 local x = 0
672 local co = coroutine.wrap(function () 672 local co = coroutine.wrap(function ()
673 local xx <close> = func2close(function () x = x + 1; error("@YYY") end) 673 local xx <close> = func2close(function ()
674 x = x + 1;
675 checkwarn("@XXX"); error("@YYY")
676 end)
674 local xv <close> = func2close(function () x = x + 1; error("@XXX") end) 677 local xv <close> = func2close(function () x = x + 1; error("@XXX") end)
675 coroutine.yield(100) 678 coroutine.yield(100)
676 error(200) 679 error(200)
677 end) 680 end)
678 assert(co() == 100); assert(x == 0) 681 assert(co() == 100); assert(x == 0)
679 local st, msg = pcall(co); assert(x == 2) 682 local st, msg = pcall(co); assert(x == 2)
@@ -683,10 +686,14 @@ do
683 local x = 0 686 local x = 0
684 local y = 0 687 local y = 0
685 co = coroutine.wrap(function () 688 co = coroutine.wrap(function ()
686 local xx <close> = func2close(function () y = y + 1; error("YYY") end) 689 local xx <close> = func2close(function ()
687 local xv <close> = func2close(function () x = x + 1; error("XXX") end) 690 y = y + 1; checkwarn("XXX"); error("YYY")
688 coroutine.yield(100) 691 end)
689 return 200 692 local xv <close> = func2close(function ()
693 x = x + 1; error("XXX")
694 end)
695 coroutine.yield(100)
696 return 200
690 end) 697 end)
691 assert(co() == 100); assert(x == 0) 698 assert(co() == 100); assert(x == 0)
692 local st, msg = pcall(co) 699 local st, msg = pcall(co)