Get stdout/stderr of launched task with pipe.

This commit is contained in:
Onha Choe 2017-03-23 22:42:50 -07:00 committed by onhachoe
parent 2bc4616959
commit 0d63ceb478

View File

@ -10,9 +10,13 @@
#include <process/DefaultLauncher.h>
#include <libutil/Filesystem.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
// In most cases, size of pipe will be greater than one page,
#define PIPE_BUFFER_SIZE 4096
using process::DefaultLauncher;
using libutil::Filesystem;
@ -71,6 +75,14 @@ launch(Filesystem *filesystem, Context const *context)
uid_t uid = context->userID();
gid_t gid = context->groupID();
/* Setup parent-child stdout/stderr pipe. */
int pfd[2];
bool pipe_setup_success = true;
if (pipe(pfd) == -1) {
::perror("pipe");
pipe_setup_success = false;
}
/*
* Fork new process.
*/
@ -80,6 +92,24 @@ launch(Filesystem *filesystem, Context const *context)
return ext::nullopt;
} else if (pid == 0) {
/* Fork succeeded, new process. */
if (pipe_setup_success) {
/* Setup pipe to parent, redirecting both stdout and stderr */
dup2(pfd[1], STDOUT_FILENO);
dup2(pfd[1], STDERR_FILENO);
close(pfd[0]);
close(pfd[1]);
} else {
/* No parent-child pipe setup, just ignore outputs from child */
int nullfd = open("/dev/null", O_WRONLY);
if (nullfd == -1) {
::perror("open");
::_exit(1);
}
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
close(nullfd);
}
if (::chdir(cDirectory) == -1) {
::perror("chdir");
::_exit(1);
@ -101,6 +131,24 @@ launch(Filesystem *filesystem, Context const *context)
return ext::nullopt;
} else {
/* Fork succeeded, existing process. */
if (pipe_setup_success) {
close(pfd[1]);
/* Read child's stdout/stderr through pipe, and output stdout */
while (true) {
char pin[PIPE_BUFFER_SIZE];
int readlen = read(pfd[0], &pin, sizeof(pin));
if (readlen > 0) {
fwrite(pin, readlen, 1, stdout);
} else {
if (readlen != 0) {
::perror("read");
}
break;
}
}
close(pfd[0]);
}
int status;
::waitpid(pid, &status, 0);
return WEXITSTATUS(status);