From fd610ae02535d4da9c839578faebbf4367be4e57 Mon Sep 17 00:00:00 2001 From: Oran Agra Date: Sun, 20 Sep 2020 13:43:28 +0300 Subject: [PATCH] RM_GetContextFlags provides indication that we're in a fork child (#7783) (cherry picked from commit 2458e5481434bb9c7b99813a449f6cbdf521c028) --- src/aof.c | 4 ++-- src/childinfo.c | 6 +++--- src/module.c | 5 +++-- src/rdb.c | 8 ++++---- src/redismodule.h | 2 ++ src/scripting.c | 2 +- src/server.c | 8 ++++++-- src/server.h | 11 +++++++---- 8 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/aof.c b/src/aof.c index dc50e2228..757c68807 100644 --- a/src/aof.c +++ b/src/aof.c @@ -1603,7 +1603,7 @@ int rewriteAppendOnlyFileBackground(void) { if (hasActiveChildProcess()) return C_ERR; if (aofCreatePipes() != C_OK) return C_ERR; openChildInfoPipe(); - if ((childpid = redisFork()) == 0) { + if ((childpid = redisFork(CHILD_TYPE_AOF)) == 0) { char tmpfile[256]; /* Child */ @@ -1611,7 +1611,7 @@ int rewriteAppendOnlyFileBackground(void) { redisSetCpuAffinity(server.aof_rewrite_cpulist); snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid()); if (rewriteAppendOnlyFile(tmpfile) == C_OK) { - sendChildCOWInfo(CHILD_INFO_TYPE_AOF, "AOF rewrite"); + sendChildCOWInfo(CHILD_TYPE_AOF, "AOF rewrite"); exitFromChild(0); } else { exitFromChild(1); diff --git a/src/childinfo.c b/src/childinfo.c index fa0600552..f95ae9647 100644 --- a/src/childinfo.c +++ b/src/childinfo.c @@ -76,11 +76,11 @@ void receiveChildInfo(void) { if (read(server.child_info_pipe[0],&server.child_info_data,wlen) == wlen && server.child_info_data.magic == CHILD_INFO_MAGIC) { - if (server.child_info_data.process_type == CHILD_INFO_TYPE_RDB) { + if (server.child_info_data.process_type == CHILD_TYPE_RDB) { server.stat_rdb_cow_bytes = server.child_info_data.cow_size; - } else if (server.child_info_data.process_type == CHILD_INFO_TYPE_AOF) { + } else if (server.child_info_data.process_type == CHILD_TYPE_AOF) { server.stat_aof_cow_bytes = server.child_info_data.cow_size; - } else if (server.child_info_data.process_type == CHILD_INFO_TYPE_MODULE) { + } else if (server.child_info_data.process_type == CHILD_TYPE_MODULE) { server.stat_module_cow_bytes = server.child_info_data.cow_size; } } diff --git a/src/module.c b/src/module.c index 5dd845de0..4cb4cfe20 100644 --- a/src/module.c +++ b/src/module.c @@ -1996,6 +1996,7 @@ int RM_GetContextFlags(RedisModuleCtx *ctx) { /* Presence of children processes. */ if (hasActiveChildProcess()) flags |= REDISMODULE_CTX_FLAGS_ACTIVE_CHILD; + if (server.in_fork_child) flags |= REDISMODULE_CTX_FLAGS_IS_CHILD; return flags; } @@ -6904,7 +6905,7 @@ int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data) { } openChildInfoPipe(); - if ((childpid = redisFork()) == 0) { + if ((childpid = redisFork(CHILD_TYPE_MODULE)) == 0) { /* Child */ redisSetProcTitle("redis-module-fork"); } else if (childpid == -1) { @@ -6924,7 +6925,7 @@ int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data) { * retcode will be provided to the done handler executed on the parent process. */ int RM_ExitFromChild(int retcode) { - sendChildCOWInfo(CHILD_INFO_TYPE_MODULE, "Module fork"); + sendChildCOWInfo(CHILD_TYPE_MODULE, "Module fork"); exitFromChild(retcode); return REDISMODULE_OK; } diff --git a/src/rdb.c b/src/rdb.c index 7e0d33565..fe9397624 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1385,7 +1385,7 @@ int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { server.lastbgsave_try = time(NULL); openChildInfoPipe(); - if ((childpid = redisFork()) == 0) { + if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) { int retval; /* Child */ @@ -1393,7 +1393,7 @@ int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { redisSetCpuAffinity(server.bgsave_cpulist); retval = rdbSave(filename,rsi); if (retval == C_OK) { - sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB"); + sendChildCOWInfo(CHILD_TYPE_RDB, "RDB"); } exitFromChild((retval == C_OK) ? 0 : 1); } else { @@ -2540,7 +2540,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { /* Create the child process. */ openChildInfoPipe(); - if ((childpid = redisFork()) == 0) { + if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) { /* Child */ int retval; rio rdb; @@ -2555,7 +2555,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { retval = C_ERR; if (retval == C_OK) { - sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB"); + sendChildCOWInfo(CHILD_TYPE_RDB, "RDB"); } rioFreeFd(&rdb); diff --git a/src/redismodule.h b/src/redismodule.h index 56011fae0..c0eedc221 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -112,6 +112,8 @@ #define REDISMODULE_CTX_FLAGS_ACTIVE_CHILD (1<<18) /* The next EXEC will fail due to dirty CAS (touched keys). */ #define REDISMODULE_CTX_FLAGS_MULTI_DIRTY (1<<19) +/* Redis is currently running inside background child process. */ +#define REDISMODULE_CTX_FLAGS_IS_CHILD (1<<20) /* Keyspace changes notification classes. Every class is associated with a * character for configuration purposes. diff --git a/src/scripting.c b/src/scripting.c index e43472b3a..6beb6cdbf 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1856,7 +1856,7 @@ void ldbSendLogs(void) { int ldbStartSession(client *c) { ldb.forked = (c->flags & CLIENT_LUA_DEBUG_SYNC) == 0; if (ldb.forked) { - pid_t cp = redisFork(); + pid_t cp = redisFork(CHILD_TYPE_LDB); if (cp == -1) { addReplyError(c,"Fork() failed: can't run EVAL in debugging mode."); return 0; diff --git a/src/server.c b/src/server.c index a88ffc6ee..ed416fb4c 100644 --- a/src/server.c +++ b/src/server.c @@ -2814,6 +2814,7 @@ void initServer(void) { server.aof_state = server.aof_enabled ? AOF_ON : AOF_OFF; server.hz = server.config_hz; server.pid = getpid(); + server.in_fork_child = CHILD_TYPE_NONE; server.main_thread_id = pthread_self(); server.current_client = NULL; server.fixed_time_expire = 0; @@ -4890,7 +4891,8 @@ void setupSignalHandlers(void) { * accepting writes because of a write error condition. */ static void sigKillChildHandler(int sig) { UNUSED(sig); - serverLogFromHandler(LL_WARNING, "Received SIGUSR1 in child, exiting now."); + int level = server.in_fork_child == CHILD_TYPE_MODULE? LL_VERBOSE: LL_WARNING; + serverLogFromHandler(level, "Received SIGUSR1 in child, exiting now."); exitFromChild(SERVER_CHILD_NOERROR_RETVAL); } @@ -4916,11 +4918,13 @@ void closeClildUnusedResourceAfterFork() { close(server.cluster_config_file_lock_fd); /* don't care if this fails */ } -int redisFork() { +/* purpose is one of CHILD_TYPE_ types */ +int redisFork(int purpose) { int childpid; long long start = ustime(); if ((childpid = fork()) == 0) { /* Child */ + server.in_fork_child = purpose; setOOMScoreAdj(CONFIG_OOM_BGCHILD); setupChildSignalHandlers(); closeClildUnusedResourceAfterFork(); diff --git a/src/server.h b/src/server.h index ba470c303..66d373944 100644 --- a/src/server.h +++ b/src/server.h @@ -1043,9 +1043,11 @@ struct clusterState; #endif #define CHILD_INFO_MAGIC 0xC17DDA7A12345678LL -#define CHILD_INFO_TYPE_RDB 0 -#define CHILD_INFO_TYPE_AOF 1 -#define CHILD_INFO_TYPE_MODULE 3 +#define CHILD_TYPE_NONE 0 +#define CHILD_TYPE_RDB 1 +#define CHILD_TYPE_AOF 2 +#define CHILD_TYPE_LDB 3 +#define CHILD_TYPE_MODULE 4 struct redisServer { /* General */ @@ -1059,6 +1061,7 @@ struct redisServer { the actual 'hz' field value if dynamic-hz is enabled. */ int hz; /* serverCron() calls frequency in hertz */ + int in_fork_child; /* indication that this is a fork child */ redisDb *db; dict *commands; /* Command table */ dict *orig_commands; /* Command table before command renaming. */ @@ -1889,7 +1892,7 @@ void sendChildInfo(int process_type); void receiveChildInfo(void); /* Fork helpers */ -int redisFork(); +int redisFork(int type); int hasActiveChildProcess(); void sendChildCOWInfo(int ptype, char *pname);