mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: Remove redundant fork in commandrvf
Currently the code is doing a redundant fork when passed the COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN flag. The additional sub-process does a chroot() which has no effect because all file handles are already open at that point, then simply copies its input to its output. This change simply replaces the above with a dup2 of the passed file handle to STDIN of the command process. RWMJ: Don't initialize 'pid' variable.
This commit is contained in:
committed by
Richard W.M. Jones
parent
d7a806ca1a
commit
2aa731e7c4
@@ -789,8 +789,8 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
size_t so_size = 0, se_size = 0;
|
||||
int so_fd[2], se_fd[2];
|
||||
int flag_copy_stdin = flags & COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN;
|
||||
int stdin_fd[2] = { -1, -1 };
|
||||
pid_t pid, stdin_pid = -1;
|
||||
int flag_copy_fd = flags & COMMAND_FLAG_FD_MASK;
|
||||
pid_t pid;
|
||||
int r, quit, i;
|
||||
fd_set rset, rset2;
|
||||
char buf[256];
|
||||
@@ -820,13 +820,6 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (flag_copy_stdin) {
|
||||
if (pipe (stdin_fd) == -1) {
|
||||
error (0, errno, "pipe");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
pid = fork ();
|
||||
if (pid == -1) {
|
||||
error (0, errno, "fork");
|
||||
@@ -838,9 +831,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
signal (SIGPIPE, SIG_DFL);
|
||||
close (0);
|
||||
if (flag_copy_stdin) {
|
||||
dup2 (stdin_fd[PIPE_READ], STDIN_FILENO);
|
||||
close (stdin_fd[PIPE_READ]);
|
||||
close (stdin_fd[PIPE_WRITE]);
|
||||
dup2 (flag_copy_fd, STDIN_FILENO);
|
||||
} else {
|
||||
/* Set stdin to /dev/null (ignore failure) */
|
||||
ignore_value (open ("/dev/null", O_RDONLY|O_CLOEXEC));
|
||||
@@ -862,60 +853,6 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (flag_copy_stdin) {
|
||||
int fd = flags & COMMAND_FLAG_FD_MASK;
|
||||
|
||||
stdin_pid = fork ();
|
||||
if (stdin_pid == -1) {
|
||||
error (0, errno, "fork");
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (stdin_pid == 0) { /* Child process copying stdin. */
|
||||
close (so_fd[PIPE_READ]);
|
||||
close (so_fd[PIPE_WRITE]);
|
||||
close (se_fd[PIPE_READ]);
|
||||
close (se_fd[PIPE_WRITE]);
|
||||
|
||||
close (STDOUT_FILENO);
|
||||
dup2 (stdin_fd[PIPE_WRITE], STDOUT_FILENO);
|
||||
close (stdin_fd[PIPE_READ]);
|
||||
close (stdin_fd[PIPE_WRITE]);
|
||||
|
||||
if (chroot (sysroot) == -1) {
|
||||
perror ("chroot");
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ssize_t n;
|
||||
char buffer[BUFSIZ];
|
||||
while ((n = read (fd, buffer, sizeof buffer)) > 0) {
|
||||
if (xwrite (STDOUT_FILENO, buffer, n) == -1)
|
||||
/* EPIPE error indicates the command process has exited
|
||||
* early. If the command process fails that will be caught
|
||||
* by the daemon, and if not, then it's not an error.
|
||||
*/
|
||||
_exit (errno == EPIPE ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (n == -1) {
|
||||
perror ("read");
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (close (fd) == -1) {
|
||||
perror ("close");
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
close (stdin_fd[PIPE_READ]);
|
||||
close (stdin_fd[PIPE_WRITE]);
|
||||
}
|
||||
|
||||
/* Parent process. */
|
||||
close (so_fd[PIPE_WRITE]);
|
||||
close (se_fd[PIPE_WRITE]);
|
||||
@@ -952,8 +889,8 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
}
|
||||
close (so_fd[PIPE_READ]);
|
||||
close (se_fd[PIPE_READ]);
|
||||
if (flag_copy_stdin) close (flag_copy_fd);
|
||||
waitpid (pid, NULL, 0);
|
||||
if (stdin_pid >= 0) waitpid (stdin_pid, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1035,21 +972,9 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_copy_stdin) {
|
||||
/* Check copy process didn't fail. */
|
||||
if (waitpid (stdin_pid, &r, 0) != stdin_pid) {
|
||||
perror ("waitpid");
|
||||
kill (pid, 9);
|
||||
waitpid (pid, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
|
||||
fprintf (stderr, "failed copying from input file, see earlier messages (r = %d)\n", r);
|
||||
kill (pid, 9);
|
||||
waitpid (pid, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (flag_copy_stdin && close (flag_copy_fd) == -1) {
|
||||
perror ("close");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the exit status of the command. */
|
||||
|
||||
Reference in New Issue
Block a user