mirror of https://github.com/rusefi/lua.git
lua_settop/lua_pop closes to-be-closed variables
The existence of 'lua_closeslot' is no reason for lua_pop not to close to-be-closed variables too. It is too error-prone for lua_pop not to close tbc variables being popped from the stack.
This commit is contained in:
parent
f5df7f91f7
commit
511d53a826
15
lapi.c
15
lapi.c
|
@ -173,7 +173,7 @@ LUA_API int lua_gettop (lua_State *L) {
|
||||||
|
|
||||||
LUA_API void lua_settop (lua_State *L, int idx) {
|
LUA_API void lua_settop (lua_State *L, int idx) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
StkId func;
|
StkId func, newtop;
|
||||||
ptrdiff_t diff; /* difference for new top */
|
ptrdiff_t diff; /* difference for new top */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
ci = L->ci;
|
ci = L->ci;
|
||||||
|
@ -188,12 +188,13 @@ LUA_API void lua_settop (lua_State *L, int idx) {
|
||||||
api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
|
api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
|
||||||
diff = idx + 1; /* will "subtract" index (as it is negative) */
|
diff = idx + 1; /* will "subtract" index (as it is negative) */
|
||||||
}
|
}
|
||||||
#if defined(LUA_COMPAT_5_4_0)
|
api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot");
|
||||||
if (diff < 0 && hastocloseCfunc(ci->nresults))
|
newtop = L->top + diff;
|
||||||
luaF_close(L, L->top + diff, CLOSEKTOP, 0);
|
if (diff < 0 && L->tbclist >= newtop) {
|
||||||
#endif
|
lua_assert(hastocloseCfunc(ci->nresults));
|
||||||
api_check(L, L->tbclist < L->top + diff, "cannot pop an unclosed slot");
|
luaF_close(L, newtop, CLOSEKTOP, 0);
|
||||||
L->top += diff;
|
}
|
||||||
|
L->top = newtop; /* correct top only after closing any upvalue */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4253,12 +4253,8 @@ If the new top is greater than the old one,
|
||||||
then the new elements are filled with @nil.
|
then the new elements are filled with @nil.
|
||||||
If @id{index} @N{is 0}, then all stack elements are removed.
|
If @id{index} @N{is 0}, then all stack elements are removed.
|
||||||
|
|
||||||
For compatibility reasons,
|
This function can run arbitrary code when removing an index
|
||||||
this function may close slots marked as to-be-closed @see{lua_toclose},
|
marked as to-be-closed from the stack.
|
||||||
and therefore it can run arbitrary code.
|
|
||||||
You should not rely on this behavior:
|
|
||||||
Instead, always close to-be-closed slots explicitly,
|
|
||||||
with @Lid{lua_closeslot}, before removing them from the stack.
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4347,19 +4343,22 @@ otherwise, returns @id{NULL}.
|
||||||
@apii{0,0,m}
|
@apii{0,0,m}
|
||||||
|
|
||||||
Marks the given index in the stack as a
|
Marks the given index in the stack as a
|
||||||
to-be-closed @Q{variable} @see{to-be-closed}.
|
to-be-closed slot @see{to-be-closed}.
|
||||||
Like a to-be-closed variable in Lua,
|
Like a to-be-closed variable in Lua,
|
||||||
the value at that index in the stack will be closed
|
the value at that slot in the stack will be closed
|
||||||
when it goes out of scope.
|
when it goes out of scope.
|
||||||
Here, in the context of a C function,
|
Here, in the context of a C function,
|
||||||
to go out of scope means that the running function returns to Lua,
|
to go out of scope means that the running function returns to Lua,
|
||||||
there is an error,
|
or there is an error,
|
||||||
|
or the slot is removed from the stack through
|
||||||
|
@Lid{lua_settop} or @Lid{lua_pop},
|
||||||
or there is a call to @Lid{lua_closeslot}.
|
or there is a call to @Lid{lua_closeslot}.
|
||||||
An index marked as to-be-closed should neither be removed from the stack
|
A slot marked as to-be-closed should not be removed from the stack
|
||||||
nor modified before a corresponding call to @Lid{lua_closeslot}.
|
by any other function in the API except @Lid{lua_settop} or @Lid{lua_pop},
|
||||||
|
unless previously deactivated by @Lid{lua_closeslot}.
|
||||||
|
|
||||||
This function should not be called for an index
|
This function should not be called for an index
|
||||||
that is equal to or below an active to-be-closed index.
|
that is equal to or below an active to-be-closed slot.
|
||||||
|
|
||||||
Note that, both in case of errors and of a regular return,
|
Note that, both in case of errors and of a regular return,
|
||||||
by the time the @idx{__close} metamethod runs,
|
by the time the @idx{__close} metamethod runs,
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ do
|
||||||
-- closing resources with 'closeslot'
|
-- closing resources with 'closeslot'
|
||||||
_ENV.xxx = true
|
_ENV.xxx = true
|
||||||
local a = T.testC([[
|
local a = T.testC([[
|
||||||
pushvalue 2 # stack: S, NR, CH
|
pushvalue 2 # stack: S, NR, CH, NR
|
||||||
call 0 1 # create resource; stack: S, NR, CH, R
|
call 0 1 # create resource; stack: S, NR, CH, R
|
||||||
toclose -1 # mark it to be closed
|
toclose -1 # mark it to be closed
|
||||||
pushvalue 2 # stack: S, NR, CH, R, NR
|
pushvalue 2 # stack: S, NR, CH, R, NR
|
||||||
|
@ -1151,6 +1151,30 @@ do
|
||||||
]], newresource, check)
|
]], newresource, check)
|
||||||
assert(a == 3 and _ENV.xxx == nil) -- no extra items left in the stack
|
assert(a == 3 and _ENV.xxx == nil) -- no extra items left in the stack
|
||||||
|
|
||||||
|
-- closing resources with 'pop'
|
||||||
|
local a = T.testC([[
|
||||||
|
pushvalue 2 # stack: S, NR, CH, NR
|
||||||
|
call 0 1 # create resource; stack: S, NR, CH, R
|
||||||
|
toclose -1 # mark it to be closed
|
||||||
|
pushvalue 2 # stack: S, NR, CH, R, NR
|
||||||
|
call 0 1 # create another resource; stack: S, NR, CH, R, R
|
||||||
|
toclose -1 # mark it to be closed
|
||||||
|
pushvalue 3 # stack: S, NR, CH, R, R, CH
|
||||||
|
pushint 2 # there should be two open resources
|
||||||
|
call 1 0 # stack: S, NR, CH, R, R
|
||||||
|
pop 1 # pop second resource
|
||||||
|
pushvalue 3 # stack: S, NR, CH, R, CH
|
||||||
|
pushint 1 # there should be one open resource
|
||||||
|
call 1 0 # stack: S, NR, CH, R
|
||||||
|
pop 1 # pop other resource from the stack
|
||||||
|
pushvalue 3 # stack: S, NR, CH, CH
|
||||||
|
pushint 0 # there should be no open resources
|
||||||
|
call 1 0 # stack: S, NR, CH
|
||||||
|
pushint *
|
||||||
|
return 1 # return stack size
|
||||||
|
]], newresource, check)
|
||||||
|
assert(a == 3) -- no extra items left in the stack
|
||||||
|
|
||||||
-- non-closable value
|
-- non-closable value
|
||||||
local a, b = pcall(T.makeCfunc[[
|
local a, b = pcall(T.makeCfunc[[
|
||||||
pushint 32
|
pushint 32
|
||||||
|
|
Loading…
Reference in New Issue