diff options
-rw-r--r-- | lstate.c | 3 | ||||
-rw-r--r-- | testes/coroutine.lua | 19 |
2 files changed, 22 insertions, 0 deletions
@@ -272,7 +272,9 @@ static void close_state (lua_State *L) { | |||
272 | luaC_freeallobjects(L); /* just collect its objects */ | 272 | luaC_freeallobjects(L); /* just collect its objects */ |
273 | else { /* closing a fully built state */ | 273 | else { /* closing a fully built state */ |
274 | L->ci = &L->base_ci; /* unwind CallInfo list */ | 274 | L->ci = &L->base_ci; /* unwind CallInfo list */ |
275 | L->errfunc = 0; /* stack unwind can "throw away" the error function */ | ||
275 | luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ | 276 | luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ |
277 | L->top.p = L->stack.p + 1; /* empty the stack to run finalizers */ | ||
276 | luaC_freeallobjects(L); /* collect all objects */ | 278 | luaC_freeallobjects(L); /* collect all objects */ |
277 | luai_userstateclose(L); | 279 | luai_userstateclose(L); |
278 | } | 280 | } |
@@ -328,6 +330,7 @@ int luaE_resetthread (lua_State *L, int status) { | |||
328 | if (status == LUA_YIELD) | 330 | if (status == LUA_YIELD) |
329 | status = LUA_OK; | 331 | status = LUA_OK; |
330 | L->status = LUA_OK; /* so it can run __close metamethods */ | 332 | L->status = LUA_OK; /* so it can run __close metamethods */ |
333 | L->errfunc = 0; /* stack unwind can "throw away" the error function */ | ||
331 | status = luaD_closeprotected(L, 1, status); | 334 | status = luaD_closeprotected(L, 1, status); |
332 | if (status != LUA_OK) /* errors? */ | 335 | if (status != LUA_OK) /* errors? */ |
333 | luaD_seterrorobj(L, status, L->stack.p + 1); | 336 | luaD_seterrorobj(L, status, L->stack.p + 1); |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index e566c86e..03e04451 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -493,6 +493,25 @@ assert(not pcall(a, a)) | |||
493 | a = nil | 493 | a = nil |
494 | 494 | ||
495 | 495 | ||
496 | do | ||
497 | -- bug in 5.4: thread can use message handler higher in the stack | ||
498 | -- than the variable being closed | ||
499 | local c = coroutine.create(function() | ||
500 | local clo <close> = setmetatable({}, {__close=function() | ||
501 | local x = 134 -- will overwrite message handler | ||
502 | error(x) | ||
503 | end}) | ||
504 | -- yields coroutine but leaves a new message handler for it, | ||
505 | -- that would be used when closing the coroutine (except that it | ||
506 | -- will be overwritten) | ||
507 | xpcall(coroutine.yield, function() return "XXX" end) | ||
508 | end) | ||
509 | |||
510 | assert(coroutine.resume(c)) -- start coroutine | ||
511 | local st, msg = coroutine.close(c) | ||
512 | assert(not st and msg == 134) | ||
513 | end | ||
514 | |||
496 | -- access to locals of erroneous coroutines | 515 | -- access to locals of erroneous coroutines |
497 | local x = coroutine.create (function () | 516 | local x = coroutine.create (function () |
498 | local a = 10 | 517 | local a = 10 |