From 44aa22c63553d6be2879c51161feb50c1b31eab8 Mon Sep 17 00:00:00 2001
From: Madelyn Olson <matolson@amazon.com>
Date: Mon, 28 Oct 2019 12:58:03 -0700
Subject: [PATCH] Added better exception handling around scripting and module

---
 src/module.c    | 11 +++++++++--
 src/scripting.c | 16 ++++++++++++----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/src/module.c b/src/module.c
index 5d9a39387..31d337b14 100644
--- a/src/module.c
+++ b/src/module.c
@@ -3174,6 +3174,8 @@ fmterr:
  * EINVAL: wrong command arity.
  * ENOENT: command does not exist.
  * EPERM:  operation in Cluster instance with key in non local slot.
+ * EROFS:  operation in Cluster instance when a write command is sent
+ *         in a readonly state.
  *
  * This API is documented here: https://redis.io/topics/modules-intro
  */
@@ -3231,13 +3233,18 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
      * trying to access non-local keys, with the exception of commands
      * received from our master. */
     if (server.cluster_enabled && !(ctx->client->flags & CLIENT_MASTER)) {
+        int error_code;
         /* Duplicate relevant flags in the module client. */
         c->flags &= ~(CLIENT_READONLY|CLIENT_ASKING);
         c->flags |= ctx->client->flags & (CLIENT_READONLY|CLIENT_ASKING);
-        if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,NULL) !=
+        if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,&error_code) !=
                            server.cluster->myself)
         {
-            errno = EPERM;
+            if (error_code == CLUSTER_REDIR_DOWN_STATE) { 
+                errno = EROFS;
+            } else {
+                errno = EPERM;
+            }
             goto cleanup;
         }
     }
diff --git a/src/scripting.c b/src/scripting.c
index 7cf21f408..c627207d5 100644
--- a/src/scripting.c
+++ b/src/scripting.c
@@ -679,15 +679,23 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
     if (server.cluster_enabled && !server.loading &&
         !(server.lua_caller->flags & CLIENT_MASTER))
     {
+        int error_code;
         /* Duplicate relevant flags in the lua client. */
         c->flags &= ~(CLIENT_READONLY|CLIENT_ASKING);
         c->flags |= server.lua_caller->flags & (CLIENT_READONLY|CLIENT_ASKING);
-        if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,NULL) !=
+        if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,&error_code) !=
                            server.cluster->myself)
         {
-            luaPushError(lua,
-                "Lua script attempted to access a non local key in a "
-                "cluster node");
+            if (error_code == CLUSTER_REDIR_DOWN_STATE) { 
+                luaPushError(lua,
+                    "Lua script attempted execute a write command while "
+                    "cluster is down");
+            } else {
+                luaPushError(lua,
+                    "Lua script attempted to access a non local key in a "
+                    "cluster node");
+            }
+
             goto cleanup;
         }
     }