PLearn 0.1
|
#include <Popen.h>
Public Member Functions | |
Popen (const string &command, bool the_verbose=false, bool redirect_stderr=false) | |
Popen (const string &command, const vector< string > &commandoptions, bool the_verbose=false, bool redirect_stderr=false) | |
int | wait () |
Wait for process termination and return exit value. | |
~Popen () | |
Close the pipes and forcibly terminate the process. | |
Public Attributes | |
PStream | in |
PStream | out |
PStream | err |
Protected Member Functions | |
void | launch (const string &command, const vector< string > &commandoptions, bool redirect_stderr=false) |
Multi-argument variant: the arguments are passed in a vector. | |
void | launch (const string &commandline, bool redirect_stderr=false) |
Full text variant. | |
Protected Attributes | |
bool | verbose |
bool | process_alive |
PRProcess * | process |
PLearn::Popen::~Popen | ( | ) |
Close the pipes and forcibly terminate the process.
If you wait until the process terminates by itself, you should call the wait() member function before the destructor is called.
Definition at line 188 of file Popen.cc.
{ // If we get here, there's no way the caller that instantiated us will be // reading any more from the process at the other end of the pipe, and they // won't be able to retrieve the exit code either. So just make sure we // don't hang on the wait and that we don't leave zombie processes around. PR_KillProcess(process); wait(); }
void PLearn::Popen::launch | ( | const string & | command, |
const vector< string > & | commandoptions, | ||
bool | redirect_stderr = false |
||
) | [protected] |
Multi-argument variant: the arguments are passed in a vector.
Definition at line 57 of file Popen.cc.
References PLearn::getPrErrorString(), i, in, PLERROR, and PLearn::quote_string().
{ // Create pipes to communicate to/from child process. PRFileDesc* stdout_child; PRFileDesc* stdout_parent; if (PR_CreatePipe(&stdout_parent, &stdout_child) != PR_SUCCESS) PLERROR("Popen: error creating first pipe pair. (%s)", getPrErrorString().c_str()); PRFileDesc* stdin_child; PRFileDesc* stdin_parent; if (PR_CreatePipe(&stdin_child, &stdin_parent) != PR_SUCCESS) { PR_Close(stdout_child); PR_Close(stdout_parent); PLERROR("Popen: error creating second pipe pair. (%s)", getPrErrorString().c_str()); } PRFileDesc* stderr_child; PRFileDesc* stderr_parent; if(redirect_stderr) if (PR_CreatePipe(&stderr_child, &stderr_parent) != PR_SUCCESS) { PR_Close(stderr_child); PR_Close(stderr_parent); PLERROR("Popen: error creating third (err) pipe pair. (%s)", getPrErrorString().c_str()); } // Set up redirection of stdin/stdout for the (future) child process. PRProcessAttr* process_attr = PR_NewProcessAttr(); PR_ProcessAttrSetStdioRedirect(process_attr, PR_StandardInput, stdin_child); PR_ProcessAttrSetStdioRedirect(process_attr, PR_StandardOutput, stdout_child); if(redirect_stderr) PR_ProcessAttrSetStdioRedirect(process_attr, PR_StandardError, stderr_child); // Set up argument list for the CreateProcess call. args[0] shoud be the // name of the program. args[1]...arg[n] hold the actual arguments, // arg[n+1] is NULL. #if !defined(_MINGW_) && !defined(WIN32) const char** args = new const char*[4]; // NSPR doesn't have a way to search through the PATH when creating // a new process. Use /bin/sh for now to spawn the process as a workaround. args[0] = "/bin/sh"; args[1] = "-c"; string concatenated_args = program; for (vector<string>::const_iterator it = arguments.begin(); it != arguments.end(); ++it) concatenated_args += " "+quote_string(*it); args[2] = concatenated_args.c_str(); args[3] = 0; process = PR_CreateProcess("/bin/sh", const_cast<char* const *>(args), NULL, process_attr); #else const char** args = new const char*[arguments.size()+2]; // PR_CreateProcess on Windows goes through the PATH. // No workaround needed here. args[0] = program.c_str(); int i = 1; for (vector<string>::const_iterator it = arguments.begin(); it != arguments.end(); ++it) args[i++] = it->c_str(); args[i] = 0; process = PR_CreateProcess(program.c_str(), const_cast<char* const *>(args), NULL, process_attr); #endif // Important: close unused files in the parent. PR_Close(stdin_child); PR_Close(stdout_child); if(redirect_stderr) PR_Close(stderr_child); delete[] args; if (!process) { PR_Close(stdin_parent); PR_Close(stdout_parent); if(redirect_stderr) PR_Close(stderr_parent); PLERROR("Popen: could not create subprocess for command '%s'. (%s)", program.c_str(), getPrErrorString().c_str()); } process_alive = true; in = new PrPStreamBuf(stdout_parent, stdin_parent); in.setBufferCapacities(0, 0, 0); out = in; if(redirect_stderr) { err= new PrPStreamBuf(stderr_parent); err.setBufferCapacities(0, 0, 0); } }
void PLearn::Popen::launch | ( | const string & | commandline, |
bool | redirect_stderr = false |
||
) | [protected] |
Full text variant.
All arguments are passed together in a string.
Definition at line 160 of file Popen.cc.
References PLearn::openString(), and PLearn::PStream::plearn_ascii.
{ // Parse command line into individual argments string tmp_commandline = "[" + commandline + "]"; PStream s = openString(tmp_commandline, PStream::plearn_ascii); vector<string> command_and_args; s >> command_and_args; const string command = command_and_args[0]; const vector<string> args(command_and_args.begin()+1, command_and_args.end()); launch(command, args, redirect_stderr); }
int PLearn::Popen::wait | ( | ) |
Wait for process termination and return exit value.
Definition at line 175 of file Popen.cc.
References PLearn::getPrErrorString(), and PLERROR.
{ int status = 0; if (process_alive) if (PR_WaitProcess(process, &status) != PR_SUCCESS) PLERROR("Popen: error while waiting for subprocess to terminate. (%s)", getPrErrorString().c_str()); process_alive = false; return status; }
Definition at line 75 of file Popen.h.
Referenced by PLearn::MatlabInterface::eigs_r11(), PLearn::execute(), PLearn::matlabR11eigs(), and PLearn::PyPLearnScript::process().
PRProcess* PLearn::Popen::process [protected] |
bool PLearn::Popen::process_alive [protected] |
bool PLearn::Popen::verbose [protected] |