Refactored nxt_process_create() for more explicit pipe closing.

This commit is contained in:
Valentin Bartenev
2019-09-26 16:03:02 +03:00
parent 9c06bfdf2c
commit f2c0f2899a

View File

@@ -42,7 +42,8 @@ nxt_bool_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
static nxt_int_t static nxt_int_t
nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd) { nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
{
pid_t rpid, pid; pid_t rpid, pid;
ssize_t n; ssize_t n;
nxt_int_t parent_status; nxt_int_t parent_status;
@@ -87,11 +88,6 @@ nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
return NXT_ERROR; return NXT_ERROR;
} }
if (nxt_slow_path(close(parentfd) == -1)) {
nxt_alert(task, "failed to close reader pipe fd");
return NXT_ERROR;
}
if (nxt_slow_path(parent_status != NXT_OK)) { if (nxt_slow_path(parent_status != NXT_OK)) {
return parent_status; return parent_status;
} }
@@ -153,36 +149,25 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
#if (NXT_HAVE_CLONE) #if (NXT_HAVE_CLONE)
pid = nxt_clone(SIGCHLD | init->isolation.clone.flags); pid = nxt_clone(SIGCHLD | init->isolation.clone.flags);
#else
pid = fork();
#endif
if (nxt_slow_path(pid < 0)) { if (nxt_slow_path(pid < 0)) {
#if (NXT_HAVE_CLONE)
nxt_alert(task, "clone() failed while creating \"%s\" %E", nxt_alert(task, "clone() failed while creating \"%s\" %E",
init->name, nxt_errno); init->name, nxt_errno);
goto cleanup;
}
#else #else
pid = fork();
if (nxt_slow_path(pid < 0)) {
nxt_alert(task, "fork() failed while creating \"%s\" %E", nxt_alert(task, "fork() failed while creating \"%s\" %E",
init->name, nxt_errno); init->name, nxt_errno);
goto cleanup;
}
#endif #endif
if (nxt_slow_path(close(pipefd[0]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno);
}
if (nxt_slow_path(close(pipefd[1]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno);
}
return pid;
}
if (pid == 0) { if (pid == 0) {
/* Child. */ /* Child. */
if (nxt_slow_path(close(pipefd[1]) == -1)) { if (nxt_slow_path(close(pipefd[1]) == -1)) {
nxt_alert(task, "failed to close writer pipe fd"); nxt_alert(task, "failed to close writer pipe fd");
return NXT_ERROR;
} }
ret = nxt_process_worker_setup(task, process, pipefd[0]); ret = nxt_process_worker_setup(task, process, pipefd[0]);
@@ -190,6 +175,10 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
exit(1); exit(1);
} }
if (nxt_slow_path(close(pipefd[0]) == -1)) {
nxt_alert(task, "failed to close writer pipe fd");
}
/* /*
* Explicitly return 0 to notice the caller function this is the child. * Explicitly return 0 to notice the caller function this is the child.
* The caller must return to the event engine work queue loop. * The caller must return to the event engine work queue loop.
@@ -199,10 +188,6 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
/* Parent. */ /* Parent. */
if (nxt_slow_path(close(pipefd[0]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno);
}
/* /*
* At this point, the child process is blocked reading the * At this point, the child process is blocked reading the
* pipe fd to get its real pid (rpid). * pipe fd to get its real pid (rpid).
@@ -219,14 +204,14 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
if (nxt_slow_path(write(pipefd[1], &pid, sizeof(pid)) == -1)) { if (nxt_slow_path(write(pipefd[1], &pid, sizeof(pid)) == -1)) {
nxt_alert(task, "failed to write real pid"); nxt_alert(task, "failed to write real pid");
goto fail_cleanup; goto fail;
} }
#if (NXT_HAVE_CLONE_NEWUSER) #if (NXT_HAVE_CLONE_NEWUSER)
if ((init->isolation.clone.flags & CLONE_NEWUSER) == CLONE_NEWUSER) { if ((init->isolation.clone.flags & CLONE_NEWUSER) == CLONE_NEWUSER) {
ret = nxt_clone_proc_map(task, pid, &init->isolation.clone); ret = nxt_clone_proc_map(task, pid, &init->isolation.clone);
if (nxt_slow_path(ret != NXT_OK)) { if (nxt_slow_path(ret != NXT_OK)) {
goto fail_cleanup; goto fail;
} }
} }
#endif #endif
@@ -235,20 +220,16 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
if (nxt_slow_path(write(pipefd[1], &ret, sizeof(ret)) == -1)) { if (nxt_slow_path(write(pipefd[1], &ret, sizeof(ret)) == -1)) {
nxt_alert(task, "failed to write status"); nxt_alert(task, "failed to write status");
goto fail_cleanup; goto fail;
}
if (nxt_slow_path(close(pipefd[1]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno);
} }
process->pid = pid; process->pid = pid;
nxt_runtime_process_add(task, process); nxt_runtime_process_add(task, process);
return pid; goto cleanup;
fail_cleanup: fail:
ret = NXT_ERROR; ret = NXT_ERROR;
@@ -256,13 +237,21 @@ fail_cleanup:
nxt_alert(task, "failed to write status"); nxt_alert(task, "failed to write status");
} }
waitpid(pid, NULL, 0);
pid = -1;
cleanup:
if (nxt_slow_path(close(pipefd[0]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno);
}
if (nxt_slow_path(close(pipefd[1]) != 0)) { if (nxt_slow_path(close(pipefd[1]) != 0)) {
nxt_alert(task, "failed to close pipe: %E", nxt_errno); nxt_alert(task, "failed to close pipe: %E", nxt_errno);
} }
waitpid(pid, NULL, 0); return pid;
return -1;
} }