Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
79de8f3c
Unverified
Commit
79de8f3c
authored
Feb 27, 2020
by
Salvatore Sanfilippo
Committed by
GitHub
Feb 27, 2020
Browse files
Merge pull request #6922 from guybe7/refix_blocked_module_memleak
Modules: Do not auto-unblock clients if not blocked on keys
parents
685dcaa1
376a806b
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/module.c
View file @
79de8f3c
...
@@ -4290,12 +4290,15 @@ void unblockClientFromModule(client *c) {
...
@@ -4290,12 +4290,15 @@ void unblockClientFromModule(client *c) {
* We must call moduleUnblockClient in order to free privdata and
* We must call moduleUnblockClient in order to free privdata and
* RedisModuleBlockedClient.
* RedisModuleBlockedClient.
*
*
* Note that clients implementing threads and working with private data,
* Note that we only do that for clients that are blocked on keys, for which
* should make sure to stop the threads or protect the private data
* the contract is that the module should not call RM_UnblockClient under
* in some other way in the disconnection and timeout callback, because
* normal circumstances.
* here we are going to free the private data associated with the
* Clients implementing threads and working with private data should be
* blocked client. */
* aware that calling RM_UnblockClient for every blocked client is their
if
(
!
bc
->
unblocked
)
* responsibility, and if they fail to do so memory may leak. Ideally they
* should implement the disconnect and timeout callbacks and call
* RM_UnblockClient, but any other way is also acceptable. */
if
(
bc
->
blocked_on_keys
&&
!
bc
->
unblocked
)
moduleUnblockClient
(
c
);
moduleUnblockClient
(
c
);
bc
->
client
=
NULL
;
bc
->
client
=
NULL
;
...
@@ -4409,6 +4412,10 @@ int moduleTryServeClientBlockedOnKey(client *c, robj *key) {
...
@@ -4409,6 +4412,10 @@ int moduleTryServeClientBlockedOnKey(client *c, robj *key) {
*
*
* free_privdata: called in order to free the private data that is passed
* free_privdata: called in order to free the private data that is passed
* by RedisModule_UnblockClient() call.
* by RedisModule_UnblockClient() call.
*
* Note: RedisModule_UnblockClient should be called for every blocked client,
* even if client was killed, timed-out or disconnected. Failing to do so
* will result in memory leaks.
*/
*/
RedisModuleBlockedClient
*
RM_BlockClient
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
)
{
RedisModuleBlockedClient
*
RM_BlockClient
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
)
{
return
moduleBlockClient
(
ctx
,
reply_callback
,
timeout_callback
,
free_privdata
,
timeout_ms
,
NULL
,
0
,
NULL
);
return
moduleBlockClient
(
ctx
,
reply_callback
,
timeout_callback
,
free_privdata
,
timeout_ms
,
NULL
,
0
,
NULL
);
...
@@ -4463,7 +4470,15 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc
...
@@ -4463,7 +4470,15 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc
* freed using the free_privdata callback provided by the user.
* freed using the free_privdata callback provided by the user.
*
*
* However the reply callback will be able to access the argument vector of
* However the reply callback will be able to access the argument vector of
* the command, so the private data is often not needed. */
* the command, so the private data is often not needed.
*
* Note: Under normal circumstances RedisModule_UnblockClient should not be
* called for clients that are blocked on keys (Either the key will
* become ready or a timeout will occur). If for some reason you do want
* to call RedisModule_UnblockClient it is possible: Client will be
* handled as if it were timed-out (You must implement the timeout
* callback in that case).
*/
RedisModuleBlockedClient
*
RM_BlockClientOnKeys
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
,
RedisModuleString
**
keys
,
int
numkeys
,
void
*
privdata
)
{
RedisModuleBlockedClient
*
RM_BlockClientOnKeys
(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
,
RedisModuleString
**
keys
,
int
numkeys
,
void
*
privdata
)
{
return
moduleBlockClient
(
ctx
,
reply_callback
,
timeout_callback
,
free_privdata
,
timeout_ms
,
keys
,
numkeys
,
privdata
);
return
moduleBlockClient
(
ctx
,
reply_callback
,
timeout_callback
,
free_privdata
,
timeout_ms
,
keys
,
numkeys
,
privdata
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment