summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/module.c13
-rw-r--r--tests/modules/blockedclient.c20
-rw-r--r--tests/unit/moduleapi/blockedclient.tcl13
3 files changed, 42 insertions, 4 deletions
diff --git a/src/module.c b/src/module.c
index a1f6a66f5..724b877f6 100644
--- a/src/module.c
+++ b/src/module.c
@@ -5783,7 +5783,16 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
if (flags & REDISMODULE_ARGV_RESPECT_DENY_OOM) {
if (cmd->flags & CMD_DENYOOM) {
- if (server.pre_command_oom_state) {
+ int oom_state;
+ if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) {
+ /* On background thread we can not count on server.pre_command_oom_state.
+ * Because it is only set on the main thread, in such case we will check
+ * the actual memory usage. */
+ oom_state = (getMaxmemoryState(NULL,NULL,NULL,NULL) == C_ERR);
+ } else {
+ oom_state = server.pre_command_oom_state;
+ }
+ if (oom_state) {
errno = ENOSPC;
if (error_as_call_replies) {
sds msg = sdsdup(shared.oomerr->ptr);
@@ -5823,7 +5832,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
}
int deny_write_type = writeCommandsDeniedByDiskError();
- int obey_client = mustObeyClient(server.current_client);
+ int obey_client = (server.current_client && mustObeyClient(server.current_client));
if (deny_write_type != DISK_ERROR_TYPE_NONE && !obey_client) {
errno = ESPIPE;
diff --git a/tests/modules/blockedclient.c b/tests/modules/blockedclient.c
index 9c2598a34..f4234b0d3 100644
--- a/tests/modules/blockedclient.c
+++ b/tests/modules/blockedclient.c
@@ -7,6 +7,7 @@
#include <assert.h>
#include <stdio.h>
#include <pthread.h>
+#include <strings.h>
#define UNUSED(V) ((void) V)
@@ -119,8 +120,20 @@ void *bg_call_worker(void *arg) {
}
// Call the command
- const char* cmd = RedisModule_StringPtrLen(bg->argv[1], NULL);
- RedisModuleCallReply* rep = RedisModule_Call(ctx, cmd, "v", bg->argv + 2, bg->argc - 2);
+ const char *module_cmd = RedisModule_StringPtrLen(bg->argv[0], NULL);
+ int cmd_pos = 1;
+ RedisModuleString *format_redis_str = RedisModule_CreateString(NULL, "v", 1);
+ if (!strcasecmp(module_cmd, "do_bg_rm_call_format")) {
+ cmd_pos = 2;
+ size_t format_len;
+ const char *format = RedisModule_StringPtrLen(bg->argv[1], &format_len);
+ RedisModule_StringAppendBuffer(NULL, format_redis_str, format, format_len);
+ RedisModule_StringAppendBuffer(NULL, format_redis_str, "E", 1);
+ }
+ const char *format = RedisModule_StringPtrLen(format_redis_str, NULL);
+ const char *cmd = RedisModule_StringPtrLen(bg->argv[cmd_pos], NULL);
+ RedisModuleCallReply *rep = RedisModule_Call(ctx, cmd, format, bg->argv + cmd_pos + 1, bg->argc - cmd_pos - 1);
+ RedisModule_FreeString(NULL, format_redis_str);
// Release GIL
RedisModule_ThreadSafeContextUnlock(ctx);
@@ -306,6 +319,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if (RedisModule_CreateCommand(ctx, "do_bg_rm_call", do_bg_rm_call, "", 0, 0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
+ if (RedisModule_CreateCommand(ctx, "do_bg_rm_call_format", do_bg_rm_call, "", 0, 0, 0) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
if (RedisModule_CreateCommand(ctx, "do_fake_bg_true", do_fake_bg_true, "", 0, 0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
diff --git a/tests/unit/moduleapi/blockedclient.tcl b/tests/unit/moduleapi/blockedclient.tcl
index dd6085c81..2cb44788e 100644
--- a/tests/unit/moduleapi/blockedclient.tcl
+++ b/tests/unit/moduleapi/blockedclient.tcl
@@ -76,6 +76,19 @@ start_server {tags {"modules"}} {
r do_bg_rm_call hgetall hash
} {foo bar}
+ test {RM_Call from blocked client with script mode} {
+ r do_bg_rm_call_format S hset k foo bar
+ } {1}
+
+ test {RM_Call from blocked client with oom mode} {
+ r config set maxmemory 1
+ # will set server.pre_command_oom_state to 1
+ assert_error {OOM command not allowed*} {r hset hash foo bar}
+ r config set maxmemory 0
+ # now its should be OK to call OOM commands
+ r do_bg_rm_call_format M hset k1 foo bar
+ } {1} {needs:config-maxmemory}
+
test {RESP version carries through to blocked client} {
for {set client_proto 2} {$client_proto <= 3} {incr client_proto} {
r hello $client_proto