std::string command = ...;
ACE_Process_Options opt;
// The child process to spawn.
opt.command_line(command.c_str());
// Define the two handles for the pipe,
// fd[0] will be used for stdin
// fd[1] will be used for stdout.
ACE_HANDLE fd[2];
// Create a pipe from the two file handles.
// Pipe between stdin and stdout.
// fd[0] <-> fd[1]
if (ACE_OS::pipe(fd) == -1)
ACE_DEBUG ((LM_ERROR, "%p\n", "pipe failed"));
// Set the stdin and stdout of the process to our file handles.
// fd[0] is used for stdin, fd[1] is used for stdout.
opt.set_handles(fd[0] /*stdin*/, fd[1] /*stdout*/);
// Spawn the child process.
ACE_Process proc;
if (proc.spawn(opt) == -1)
ACE_DEBUG ((LM_ERROR, "%p\n", "spawn failed"));
// Wait for the process to finish.
ACE_exitcode exitcode = 0;
proc.wait(&exitcode);
// After fork:
// fd[0] <-> fd[1] child
// fd'[0] <-> fd'[1] parent
// Need to close parent stdout or parent will be trying to read from it forever.
// With stdout closed parent will get EOF from the child so that the parent
// will know the child is done.
if (ACE_OS::close(fd[1]) == -1)
ACE_DEBUG ((LM_ERROR, "%p\n", "close stdout"));
// After close:
// fd[0] <-> fd[1] child
// fd'[0] <-> parent
// which leaves our (parent) stdin piped to child's stdout
// set_handles() dups the handles, so make sure they are released.
opt.release_handles();
// Read from parent's stdin, which is connected
// to the child's stdout.
std::string child_stdout;
const size_t BUFFSIZE = 1024;
char buf[BUFFSIZE + 1];
ssize_t n = 0;
while ((n = ACE_OS::read(fd[0], buf, BUFFSIZE)) > 0) {
buf[n] = 0;
child_stdout.append(buf, n);
}
// Close stdin.
if (ACE_OS::close(fd[0]) == -1)
ACE_DEBUG ((LM_ERROR, "%p\n", "close stdin"));
Tuesday, July 12, 2005
Windows: How to capture stdout from a spawned child process
The below code is similar to my last post. However, it *does* work on Windows while the previous code only works on Unix.
Friday, July 08, 2005
How to capture stdout from a spawned child process
A recent post to ace-users reminded me how hard it was for me to figure out how to capture stdout from a spawned child process in C++. After much research and trial and error, I came up with the following which uses ACE.
Update 7/12/2005: The below code does not work on Windows because Windows does not allow redirection of stdout/stderr to sockets which is what ACE_Pipe uses. See my next post for code that does work on Windows.
Update 7/12/2005: The below code does not work on Windows because Windows does not allow redirection of stdout/stderr to sockets which is what ACE_Pipe uses. See my next post for code that does work on Windows.
std::string command = ...;
ACE_Process_Options opt;
// The child process to spawn.
opt.command_line(command.c_str());
// Define the two handles for the pipe,
// fd[0] will be used for stdin
// fd[1] will be used for stdout.
ACE_HANDLE fd[2];
// Create a pipe from the two file handles.
// Pipe between stdin and stdout.
// fd[0] <-> fd[1]
ACE_Pipe pipe(fd);
// Set the stdin and stdout of the process to our file handles.
// fd[0] is used for stdin, fd[1] is used for stdout.
opt.set_handles(fd[0] /*stdin*/, fd[1] /*stdout*/);
// Spawn the child process.
ACE_Process proc;
if (proc.spawn(opt) == -1) ACE_DEBUG ((LM_ERROR, "%p\n", "spawn failed"));
// After fork:
// fd[0] <-> fd[1] child
// fd'[0] <-> fd'[1] parent
// Need to close parent stdout or parent will be trying to read from it forever.
// With stdout closed parent will get EOF from the child so that the parent
// will know the child is done.
if (ACE_OS::close(fd[1]) == -1) ACE_DEBUG ((LM_ERROR, "%p\n", "close stdout"));
// After close:
// fd[0] <-> fd[1] child
// fd'[0] <-> parent
// which leaves our (parent) stdin piped to child's stdout
// set_handles() dups the handles, so make sure they are released.
opt.release_handles();
// Read from parent's stdin, which is connected
// to the child's stdout.
std::string child_stdout;
const size_t BUFFSIZE = 1024;
char buf[BUFFSIZE + 1];
ssize_t n = 0;
while ((n = ACE_OS::read(fd[0], buf, BUFFSIZE)) > 0) {
buf[n] = 0;
child_stdout.append(buf, n);
}
ACE_exitcode exitcode = 0;
proc.wait(&exitcode);
// Close stdin.
if (ACE_OS::close(fd[0]) == -1) ACE_DEBUG ((LM_ERROR, "%p\n", "close stdin"));
// Close the pipe, pipe destructor does not close the pipe.
pipe.close();
Subscribe to:
Posts (Atom)