From 2458e5481434bb9c7b99813a449f6cbdf521c028 Mon Sep 17 00:00:00 2001 From: Oran Agra <oran@redislabs.com> Date: Sun, 20 Sep 2020 13:43:28 +0300 Subject: [PATCH] RM_GetContextFlags provides indication that we're in a fork child (#7783) --- 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 e01a11342..c444c299c 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 c6ea0cbbb..17b72d059 100644 --- a/src/module.c +++ b/src/module.c @@ -1991,6 +1991,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; } @@ -6899,7 +6900,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) { @@ -6919,7 +6920,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 d0a3c3210..d2c085d4d 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 { @@ -2561,7 +2561,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { /* Create the child process. */ openChildInfoPipe(); - if ((childpid = redisFork()) == 0) { + if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) { /* Child */ int retval, dummy; rio rdb; @@ -2576,7 +2576,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 fdccb5db7..c8ff51b91 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1858,7 +1858,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 1ce20334c..3363d476f 100644 --- a/src/server.c +++ b/src/server.c @@ -2886,6 +2886,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; @@ -4989,7 +4990,8 @@ void removeSignalHandlers(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); } @@ -5015,11 +5017,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 1025b1654..7d27626a7 100644 --- a/src/server.h +++ b/src/server.h @@ -1046,9 +1046,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 */ @@ -1062,6 +1064,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. */ @@ -1904,7 +1907,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);