aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-03-17 14:32:08 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-03-17 14:32:08 -0300
commit921832be8d7f687d2cd891654c8680c6e9d6584c (patch)
tree0a2ec0b675d289feea0da26c8082450bdb18aaf8
parent205f9aa67b43b3d9b5059769cfc1ed0265341586 (diff)
downloadlua-921832be8d7f687d2cd891654c8680c6e9d6584c.tar.gz
lua-921832be8d7f687d2cd891654c8680c6e9d6584c.tar.bz2
lua-921832be8d7f687d2cd891654c8680c6e9d6584c.zip
New function 'resetCI'
New function 'resetCI' resets the CallInfo list of a thread, ensuring a proper state when creating a new thread, closing a thread, or closing a state, so that we can run code after that. (When closing a thread, we need to run its __close metamethods; when closing a state, we need to run its __close metamethods and its finalizers.)
-rw-r--r--lstate.c39
-rw-r--r--testes/coroutine.lua19
2 files changed, 39 insertions, 19 deletions
diff --git a/lstate.c b/lstate.c
index ed5ccaaa..20ed838f 100644
--- a/lstate.c
+++ b/lstate.c
@@ -143,25 +143,29 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) {
143} 143}
144 144
145 145
146static void resetCI (lua_State *L) {
147 CallInfo *ci = L->ci = &L->base_ci;
148 ci->func.p = L->stack.p;
149 setnilvalue(s2v(ci->func.p)); /* 'function' entry for basic 'ci' */
150 ci->top.p = ci->func.p + 1 + LUA_MINSTACK; /* +1 for 'function' entry */
151 ci->u.c.k = NULL;
152 ci->callstatus = CIST_C;
153 L->status = LUA_OK;
154 L->errfunc = 0; /* stack unwind can "throw away" the error function */
155}
156
157
146static void stack_init (lua_State *L1, lua_State *L) { 158static void stack_init (lua_State *L1, lua_State *L) {
147 int i; CallInfo *ci; 159 int i;
148 /* initialize stack array */ 160 /* initialize stack array */
149 L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); 161 L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
150 L1->tbclist.p = L1->stack.p; 162 L1->tbclist.p = L1->stack.p;
151 for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) 163 for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
152 setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ 164 setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */
153 L1->top.p = L1->stack.p;
154 L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; 165 L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
155 /* initialize first ci */ 166 /* initialize first ci */
156 ci = &L1->base_ci; 167 resetCI(L1);
157 ci->next = ci->previous = NULL; 168 L1->top.p = L1->stack.p + 1; /* +1 for 'function' entry */
158 ci->callstatus = CIST_C;
159 ci->func.p = L1->top.p;
160 ci->u.c.k = NULL;
161 setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */
162 L1->top.p++;
163 ci->top.p = L1->top.p + LUA_MINSTACK;
164 L1->ci = ci;
165} 169}
166 170
167 171
@@ -235,6 +239,7 @@ static void preinit_thread (lua_State *L, global_State *g) {
235 L->status = LUA_OK; 239 L->status = LUA_OK;
236 L->errfunc = 0; 240 L->errfunc = 0;
237 L->oldpc = 0; 241 L->oldpc = 0;
242 L->base_ci.previous = L->base_ci.next = NULL;
238} 243}
239 244
240 245
@@ -252,8 +257,9 @@ static void close_state (lua_State *L) {
252 if (!completestate(g)) /* closing a partially built state? */ 257 if (!completestate(g)) /* closing a partially built state? */
253 luaC_freeallobjects(L); /* just collect its objects */ 258 luaC_freeallobjects(L); /* just collect its objects */
254 else { /* closing a fully built state */ 259 else { /* closing a fully built state */
255 L->ci = &L->base_ci; /* unwind CallInfo list */ 260 resetCI(L);
256 luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ 261 luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
262 L->top.p = L->stack.p + 1; /* empty the stack to run finalizers */
257 luaC_freeallobjects(L); /* collect all objects */ 263 luaC_freeallobjects(L); /* collect all objects */
258 luai_userstateclose(L); 264 luai_userstateclose(L);
259 } 265 }
@@ -302,20 +308,15 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
302 308
303 309
304TStatus luaE_resetthread (lua_State *L, TStatus status) { 310TStatus luaE_resetthread (lua_State *L, TStatus status) {
305 CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ 311 resetCI(L);
306 setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */
307 ci->func.p = L->stack.p;
308 ci->callstatus = CIST_C;
309 if (status == LUA_YIELD) 312 if (status == LUA_YIELD)
310 status = LUA_OK; 313 status = LUA_OK;
311 L->status = LUA_OK; /* so it can run __close metamethods */
312 status = luaD_closeprotected(L, 1, status); 314 status = luaD_closeprotected(L, 1, status);
313 if (status != LUA_OK) /* errors? */ 315 if (status != LUA_OK) /* errors? */
314 luaD_seterrorobj(L, status, L->stack.p + 1); 316 luaD_seterrorobj(L, status, L->stack.p + 1);
315 else 317 else
316 L->top.p = L->stack.p + 1; 318 L->top.p = L->stack.p + 1;
317 ci->top.p = L->top.p + LUA_MINSTACK; 319 luaD_reallocstack(L, cast_int(L->ci->top.p - L->stack.p), 0);
318 luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0);
319 return status; 320 return status;
320} 321}
321 322
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 680fc605..17f6ceba 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -505,6 +505,25 @@ assert(not pcall(a, a))
505a = nil 505a = nil
506 506
507 507
508do
509 -- bug in 5.4: thread can use message handler higher in the stack
510 -- than the variable being closed
511 local c = coroutine.create(function()
512 local clo <close> = setmetatable({}, {__close=function()
513 local x = 134 -- will overwrite message handler
514 error(x)
515 end})
516 -- yields coroutine but leaves a new message handler for it,
517 -- that would be used when closing the coroutine (except that it
518 -- will be overwritten)
519 xpcall(coroutine.yield, function() return "XXX" end)
520 end)
521
522 assert(coroutine.resume(c)) -- start coroutine
523 local st, msg = coroutine.close(c)
524 assert(not st and msg == 134)
525end
526
508-- access to locals of erroneous coroutines 527-- access to locals of erroneous coroutines
509local x = coroutine.create (function () 528local x = coroutine.create (function ()
510 local a = 10 529 local a = 10