Skip to content

Commit 6fec23e

Browse files
bugfix: leaked ctxs slot when ngx_lua_ffi_set_ctx_ref failed.
ref_in_table() reserves a slot in the shared ctxs table before the FFI call. When ngx_http_lua_ffi_set_ctx_ref() returned non-FFI_OK (OOM registering the request-pool cleanup), the slot was never released and accumulated until the worker exited. - get_ctx_table(): release the slot before returning nil. - set_ctx_table(): the return value of the FFI call was ignored; now release the slot and raise "no memory", matching the C-side luaL_error(L, "no memory") convention. Add base.unref_in_table() as the public counterpart to base.ref_in_table() that pushes the ref onto the free list at FREE_LIST_REF, mirroring the layout used by luaL_ref/luaL_unref on the C side (both operate on the same table via the ngx_lua_ctx_tables registry key).
1 parent fb7710e commit 6fec23e

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

lib/resty/core/base.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,16 @@ function _M.ref_in_table(tb, key)
222222
end
223223

224224

225+
-- Release a slot acquired via ref_in_table() back to the free list.
226+
-- Mirrors the layout used by luaL_ref / luaL_unref on the C side (both
227+
-- use the slot at FREE_LIST_REF as the free-list head), so tables shared
228+
-- with luaL_ref/unref (e.g. ngx_lua_ctx_tables) stay consistent.
229+
function _M.unref_in_table(tb, ref)
230+
tb[ref] = tb[FREE_LIST_REF]
231+
tb[FREE_LIST_REF] = ref
232+
end
233+
234+
225235
function _M.allows_subsystem(...)
226236
local total = select("#", ...)
227237

lib/resty/core/ctx.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ local register_setter = misc.register_ngx_magic_key_setter
1313
local registry = debug.getregistry()
1414
local new_tab = base.new_tab
1515
local ref_in_table = base.ref_in_table
16+
local unref_in_table = base.unref_in_table
1617
local get_request = base.get_request
1718
local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
1819
local FFI_OK = base.FFI_OK
@@ -106,6 +107,7 @@ do
106107

107108
ctx_ref = ref_in_table(ctxs, ctx)
108109
if ngx_lua_ffi_set_ctx_ref(r, ctx_ref) ~= FFI_OK then
110+
unref_in_table(ctxs, ctx_ref)
109111
return nil
110112
end
111113
return ctx
@@ -136,7 +138,10 @@ local function set_ctx_table(ctx)
136138

137139
if ctx_ref < 0 then
138140
ctx_ref = ref_in_table(ctxs, ctx)
139-
ngx_lua_ffi_set_ctx_ref(r, ctx_ref)
141+
if ngx_lua_ffi_set_ctx_ref(r, ctx_ref) ~= FFI_OK then
142+
unref_in_table(ctxs, ctx_ref)
143+
error("no memory")
144+
end
140145
return
141146
end
142147
ctxs[ctx_ref] = ctx

0 commit comments

Comments
 (0)