Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mlcache): release lock upon exiting the renew function #12743

Merged
merged 7 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/unreleased/kong/fix-mlcache-renew-lock-leaks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
message: |
Fixed an issue that leaking locks in the internal caching logic
type: bugfix
scope: Core
30 changes: 19 additions & 11 deletions kong/resty/mlcache/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -826,14 +826,15 @@ function _M:renew(key, opts, cb, ...)

local version_before = get_version(shmerr or 0)

local lock, err = resty_lock:new(self.shm_locks, self.resty_lock_opts)
local lock, lock_err = resty_lock:new(self.shm_locks, self.resty_lock_opts)
if not lock then
return nil, "could not create lock: " .. err
return nil, "could not create lock: " .. lock_err
end

local elapsed, err = lock:lock(LOCK_KEY_PREFIX .. namespaced_key)
if not elapsed and err ~= "timeout" then
return nil, "could not acquire callback lock: " .. err
local elapsed
elapsed, lock_err = lock:lock(LOCK_KEY_PREFIX .. namespaced_key)
if not elapsed and lock_err ~= "timeout" then
return nil, "could not acquire callback lock: " .. lock_err
end

local is_hit
Expand All @@ -847,7 +848,11 @@ function _M:renew(key, opts, cb, ...)
if shmerr then
-- shmerr can be 'flags' upon successful get_stale() calls, so we
-- also check v == nil
return nil, "could not read from lua_shared_dict: " .. shmerr
if not lock_err then
return unlock_and_ret(lock, nil,
"could not read from lua_shared_dict: " .. shmerr)
end
return nil, "could not acquire callback lock: " .. lock_err
end

-- if we specified shm_miss, it might be a negative hit cached
Expand All @@ -860,7 +865,11 @@ function _M:renew(key, opts, cb, ...)
elseif shmerr then
-- shmerr can be 'flags' upon successful get_stale() calls, so we
-- also check v == nil
return nil, "could not read from lua_shared_dict (miss): " .. shmerr
if not lock_err then
return unlock_and_ret(lock, nil,
"could not read from lua_shared_dict (miss): " .. shmerr)
end
return nil, "could not acquire callback lock: " .. lock_err
end
end
end
Expand All @@ -881,20 +890,19 @@ function _M:renew(key, opts, cb, ...)

if ttl_left then
v = decode(v)
if not err then
if not lock_err then
return unlock_and_ret(lock, v, nil, ttl_left)
end
return v, nil, ttl_left
end
end
end

if err == "timeout" then
if lock_err == "timeout" then
return nil, "could not acquire callback lock: timeout"
end

local ok, data, new_ttl
ok, data, err, new_ttl = xpcall(cb, traceback, ...)
local ok, data, err, new_ttl = xpcall(cb, traceback, ...)
if not ok then
return unlock_and_ret(lock, nil, "callback threw an error: " .. tostring(data))
end
Expand Down
Loading