diff options
| -rw-r--r-- | lstate.c | 8 | ||||
| -rw-r--r-- | manual/manual.of | 10 | ||||
| -rw-r--r-- | testes/coroutine.lua | 10 | ||||
| -rw-r--r-- | testes/cstack.lua | 4 | ||||
| -rw-r--r-- | testes/locals.lua | 23 |
5 files changed, 40 insertions, 15 deletions
| @@ -323,14 +323,16 @@ void luaE_freethread (lua_State *L, lua_State *L1) { | |||
| 323 | 323 | ||
| 324 | int lua_resetthread (lua_State *L) { | 324 | int 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. | |||
| 4098 | Resets a thread, cleaning its call stack and closing all pending | 4098 | Resets a thread, cleaning its call stack and closing all pending |
| 4099 | to-be-closed variables. | 4099 | to-be-closed variables. |
| 4100 | Returns a status code: | 4100 | Returns 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 | ||
| 4103 | errors in closing methods), | ||
| 4102 | or an error status otherwise. | 4104 | or an error status otherwise. |
| 4103 | In case of error, | 4105 | In case of error, |
| 4104 | leaves the error object on the top of the stack, | 4106 | leaves the error object on the top of the stack. |
| 4105 | 4107 | ||
| 4106 | } | 4108 | } |
| 4107 | 4109 | ||
| @@ -6577,7 +6579,9 @@ that is, | |||
| 6577 | closes all its pending to-be-closed variables | 6579 | closes all its pending to-be-closed variables |
| 6578 | and puts the coroutine in a dead state. | 6580 | and puts the coroutine in a dead state. |
| 6579 | The given coroutine must be dead or suspended. | 6581 | The given coroutine must be dead or suspended. |
| 6580 | In case of error closing some variable, | 6582 | In case of error |
| 6583 | (either the original error that stopped the coroutine or | ||
| 6584 | errors in closing methods), | ||
| 6581 | returns @false plus the error object; | 6585 | returns @false plus the error object; |
| 6582 | otherwise returns @true. | 6586 | otherwise 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"+" |
| 147 | end | 151 | end |
| 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 | ||
| 363 | local function checkwarn (msg) | 363 | local 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 |
| 368 | end | 368 | end |
| @@ -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) |
