TerminateModuleForkChild(): move safety checks there.

We don't want that the API could be used directly in an unsafe way,
without checking if there is an active child. Now the safety checks are
moved directly in the function performing the operations.
This commit is contained in:
antirez 2019-09-27 12:17:47 +02:00
parent de1f82aa33
commit 721d3c9e0c
3 changed files with 20 additions and 19 deletions

View File

@ -5031,7 +5031,7 @@ int RM_UnregisterCommandFilter(RedisModuleCtx *ctx, RedisModuleCommandFilter *fi
ln = listSearchKey(moduleCommandFilters,filter);
if (!ln) return REDISMODULE_ERR;
listDelNode(moduleCommandFilters,ln);
ln = listSearchKey(ctx->module->filters,filter);
if (!ln) return REDISMODULE_ERR; /* Shouldn't happen */
listDelNode(ctx->module->filters,ln);
@ -5154,8 +5154,7 @@ int RM_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx, int pos)
* Return: -1 on failure, on success the parent process will get a positive PID
* of the child, and the child process will get 0.
*/
int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data)
{
int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data) {
pid_t childpid;
if (hasActiveChildProcess()) {
return -1;
@ -5181,14 +5180,20 @@ int RM_Fork(RedisModuleForkDoneHandler cb, void *user_data)
/* Call from the child process when you want to terminate it.
* retcode will be provided to the done handler executed on the parent process.
*/
int RM_ExitFromChild(int retcode)
{
int RM_ExitFromChild(int retcode) {
sendChildCOWInfo(CHILD_INFO_TYPE_MODULE, "Module fork");
exitFromChild(retcode);
return REDISMODULE_OK;
}
void TerminateModuleForkChild(int wait) {
/* Kill the active module forked child, if there is one active and the
* pid matches, and returns C_OK. Otherwise if there is no active module
* child or the pid does not match, return C_ERR without doing anything. */
void TerminateModuleForkChild(int child_pid, int wait) {
/* Module child should be active and pid should match. */
if (server.module_child_pid == -1 ||
server.module_child_pid != child_pid) return C_ERR;
int statloc;
serverLog(LL_NOTICE,"Killing running module fork child: %ld",
(long) server.module_child_pid);
@ -5202,24 +5207,20 @@ void TerminateModuleForkChild(int wait) {
moduleForkInfo.done_handler_user_data = NULL;
closeChildInfoPipe();
updateDictResizePolicy();
return C_OK;
}
/* Can be used to kill the forked child process from the parent process.
* child_pid whould be the return value of RedisModule_Fork. */
int RM_KillForkChild(int child_pid)
{
/* No module child? return. */
if (server.module_child_pid == -1) return REDISMODULE_ERR;
/* Make sure the module knows the pid it wants to kill (not trying to
* randomly kill other module's forks) */
if (server.module_child_pid != child_pid) return REDISMODULE_ERR;
int RM_KillForkChild(int child_pid) {
/* Kill module child, wait for child exit. */
TerminateModuleForkChild(1);
return REDISMODULE_OK;
if (TerminateModuleForkChild(child_pid,1) == C_OK)
return REDISMODULE_OK;
else
return REDISMODULE_ERR;
}
void ModuleForkDoneHandler(int exitcode, int bysignal)
{
void ModuleForkDoneHandler(int exitcode, int bysignal) {
serverLog(LL_NOTICE,
"Module fork exited pid: %d, retcode: %d, bysignal: %d",
server.module_child_pid, exitcode, bysignal);

View File

@ -3589,7 +3589,7 @@ int prepareForShutdown(int flags) {
/* Kill module child if there is one. */
if (server.module_child_pid != -1) {
serverLog(LL_WARNING,"There is a module fork child. Killing it!");
TerminateModuleForkChild(0);
TerminateModuleForkChild(server.module_child_pid,0);
}
if (server.aof_state != AOF_OFF) {

View File

@ -1552,7 +1552,7 @@ void moduleReleaseGIL(void);
void moduleNotifyKeyspaceEvent(int type, const char *event, robj *key, int dbid);
void moduleCallCommandFilters(client *c);
void ModuleForkDoneHandler(int exitcode, int bysignal);
void TerminateModuleForkChild(int wait);
void TerminateModuleForkChild(int child_pid, int wait);
ssize_t rdbSaveModulesAux(rio *rdb, int when);
int moduleAllDatatypesHandleErrors();