Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Turbo码先生
redis
提交
bf53f928
R
redis
项目概览
Turbo码先生
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
bf53f928
编写于
1月 29, 2020
作者:
S
Salvatore Sanfilippo
提交者:
GitHub
1月 29, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #6699 from guybe7/module_blocked_on_key_timeout_memleak
Modules: Fix blocked-client-related memory leak
上级
7ef2270e
d7d13721
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
51 addition
and
6 deletion
+51
-6
src/module.c
src/module.c
+9
-0
tests/modules/blockonkeys.c
tests/modules/blockonkeys.c
+7
-6
tests/unit/moduleapi/blockonkeys.tcl
tests/unit/moduleapi/blockonkeys.tcl
+35
-0
未找到文件。
src/module.c
浏览文件 @
bf53f928
...
...
@@ -4277,6 +4277,15 @@ void unblockClientFromModule(client *c) {
moduleFreeContext
(
&
ctx
);
}
/* If we made it here and client is still blocked it means that the command
* timed-out, client was killed or disconnected and disconnect_callback was
* not implemented (or it was, but RM_UnblockClient was not called from
* within it, as it should).
* We must call moduleUnblockClient in order to free privdata and
* RedisModuleBlockedClient */
if
(
!
bc
->
unblocked
)
moduleUnblockClient
(
c
);
bc
->
client
=
NULL
;
/* Reset the client for a new query since, for blocking commands implemented
* into modules, we do not it immediately after the command returns (and
...
...
tests/modules/blockonkeys.c
浏览文件 @
bf53f928
...
...
@@ -172,13 +172,13 @@ int bpopgt_reply_callback(RedisModuleCtx *ctx, RedisModuleString **argv, int arg
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModuleString
*
keyname
=
RedisModule_GetBlockedClientReadyKey
(
ctx
);
long
long
gt
=
(
long
long
)
RedisModule_GetBlockedClientPrivateData
(
ctx
);
long
long
*
pgt
=
RedisModule_GetBlockedClientPrivateData
(
ctx
);
fsl_t
*
fsl
;
if
(
!
get_fsl
(
ctx
,
keyname
,
REDISMODULE_READ
,
0
,
&
fsl
,
0
))
return
REDISMODULE_ERR
;
if
(
!
fsl
||
fsl
->
list
[
fsl
->
length
-
1
]
<=
gt
)
if
(
!
fsl
||
fsl
->
list
[
fsl
->
length
-
1
]
<=
*
p
gt
)
return
REDISMODULE_ERR
;
RedisModule_ReplyWithLongLong
(
ctx
,
fsl
->
list
[
--
fsl
->
length
]);
...
...
@@ -192,10 +192,8 @@ int bpopgt_timeout_callback(RedisModuleCtx *ctx, RedisModuleString **argv, int a
}
void
bpopgt_free_privdata
(
RedisModuleCtx
*
ctx
,
void
*
privdata
)
{
/* Nothing to do because privdata is actually a 'long long',
* not a pointer to the heap */
REDISMODULE_NOT_USED
(
ctx
);
R
EDISMODULE_NOT_USED
(
privdata
);
R
edisModule_Free
(
privdata
);
}
/* FSL.BPOPGT <key> <gt> <timeout> - Block clients until list has an element greater than <gt>.
...
...
@@ -217,9 +215,12 @@ int fsl_bpopgt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
return
REDISMODULE_OK
;
if
(
!
fsl
||
fsl
->
list
[
fsl
->
length
-
1
]
<=
gt
)
{
/* We use malloc so the tests in blockedonkeys.tcl can check for memory leaks */
long
long
*
pgt
=
RedisModule_Alloc
(
sizeof
(
long
long
));
*
pgt
=
gt
;
/* Key is empty or has <2 elements, we must block */
RedisModule_BlockClientOnKeys
(
ctx
,
bpopgt_reply_callback
,
bpopgt_timeout_callback
,
bpopgt_free_privdata
,
timeout
,
&
argv
[
1
],
1
,
(
void
*
)
gt
);
bpopgt_free_privdata
,
timeout
,
&
argv
[
1
],
1
,
p
gt
);
}
else
{
RedisModule_ReplyWithLongLong
(
ctx
,
fsl
->
list
[
--
fsl
->
length
]);
}
...
...
tests/unit/moduleapi/blockonkeys.tcl
浏览文件 @
bf53f928
...
...
@@ -45,18 +45,24 @@ start_server {tags {"modules"}} {
test
{
Module client blocked on keys
(
with metadata
)
: Timeout
}
{
r del k
set rd
[
redis_deferring_client
]
$rd client id
set cid
[
$rd
read
]
r fsl.push k 33
$rd fsl.bpopgt k 35 1
assert_equal
{
Request timedout
}
[
$rd
read
]
r client kill id $cid
;
# try to smoke-out client-related memory leak
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, case 1
}
{
r del k
set rd
[
redis_deferring_client
]
$rd client id
set cid
[
$rd
read
]
r fsl.push k 33
$rd fsl.bpopgt k 33 0
r fsl.push k 34
assert_equal
{
34
}
[
$rd
read
]
r client kill id $cid
;
# try to smoke-out client-related memory leak
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, case 2
}
{
...
...
@@ -70,6 +76,35 @@ start_server {tags {"modules"}} {
assert_equal
{
36
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, CLIENT KILL
}
{
r del k
set rd
[
redis_deferring_client
]
$rd client id
set cid
[
$rd
read
]
$rd fsl.bpopgt k 35 0
r client kill id $cid
;
# try to smoke-out client-related memory leak
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, CLIENT UNBLOCK TIMEOUT
}
{
r del k
set rd
[
redis_deferring_client
]
$rd client id
set cid
[
$rd
read
]
$rd fsl.bpopgt k 35 0
r client unblock $cid timeout
;
# try to smoke-out client-related memory leak
assert_equal
{
Request timedout
}
[
$rd
read
]
}
test
{
Module client blocked on keys
(
with metadata
)
: Blocked, CLIENT UNBLOCK ERROR
}
{
r del k
set rd
[
redis_deferring_client
]
$rd client id
set cid
[
$rd
read
]
$rd fsl.bpopgt k 35 0
r client unblock $cid error
;
# try to smoke-out client-related memory leak
assert_error
"*unblocked*"
{
$rd
read
}
}
test
{
Module client blocked on keys does not wake up on wrong type
}
{
r del k
set rd
[
redis_deferring_client
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录