starting pipes
This commit is contained in:
@@ -63,14 +63,72 @@
|
||||
//!
|
||||
|
||||
|
||||
namespace {
|
||||
enum class PipeDirection {
|
||||
Read,
|
||||
Write,
|
||||
Last = Write
|
||||
};
|
||||
|
||||
enum class StdFile {
|
||||
In,
|
||||
Out,
|
||||
Err,
|
||||
Last = Err
|
||||
};
|
||||
|
||||
constexpr int PipesDirections = static_cast<int>(PipeDirection::Last) + 1;
|
||||
constexpr int StdFileCount = static_cast<int>(StdFile::Last) + 1;
|
||||
|
||||
#ifdef WINDOWS
|
||||
using PipeHandleType = HANDLE;
|
||||
#else
|
||||
using PipeHandleType = int;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIProcess)
|
||||
# ifdef WINDOWS
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
# else
|
||||
pid_t pid;
|
||||
# endif
|
||||
FILE *tf_in, *tf_out, *tf_err;
|
||||
PipeHandleType pipes[StdFileCount][PipesDirections];
|
||||
bool grab[StdFileCount];
|
||||
|
||||
void forEachPipe(std::function<void(PipeHandleType &)> func) {
|
||||
for (int i = 0; i < StdFileCount; ++i) {
|
||||
for (int j = 0; j < PipesDirections; ++j) {
|
||||
func(pipes[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initGrab() {
|
||||
for (int i = 0; i < StdFileCount; ++i) {
|
||||
grab[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool createPipe(StdFile pipe_type) {
|
||||
const int pt = static_cast<int>(pipe_type);
|
||||
#ifdef WINDOWS
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
if (!CreatePipe(&(pipes[pt][PipeDirection::Read]), &(pipes[pt][PipeDirection::Write]), &saAttr, 0)) {
|
||||
piCout << "CreatePipe failed: " << GetLastError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
int ret = pipe(pipes[pt]);
|
||||
return ret != -1;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
PRIVATE_DEFINITION_END(PIProcess)
|
||||
|
||||
|
||||
@@ -82,18 +140,14 @@ PIProcess::PIProcess(): PIThread() {
|
||||
PRIVATE->pid = 0;
|
||||
# endif
|
||||
is_exec = false;
|
||||
g_in = g_out = g_err = false;
|
||||
t_in = t_out = t_err = false;
|
||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||
env = PIProcess::currentEnvironment();
|
||||
PRIVATE->forEachPipe([](PipeHandleType & pipe) { pipe = 0;});
|
||||
PRIVATE->initGrab();
|
||||
env = PIProcess::currentEnvironment();
|
||||
}
|
||||
|
||||
|
||||
PIProcess::~PIProcess() {
|
||||
PIThread::stopAndWait();
|
||||
if (t_in) f_in.remove();
|
||||
if (t_out) f_out.remove();
|
||||
if (t_err) f_err.remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -143,19 +197,6 @@ void PIProcess::startProc(bool detached) {
|
||||
}
|
||||
# endif
|
||||
/// files for stdin/out/err
|
||||
t_in = t_out = t_err = false;
|
||||
if (f_in.path().isEmpty()) {
|
||||
f_in.openTemporary(PIIODevice::ReadWrite);
|
||||
t_in = true;
|
||||
}
|
||||
if (f_out.path().isEmpty()) {
|
||||
f_out.openTemporary(PIIODevice::ReadWrite);
|
||||
t_out = true;
|
||||
}
|
||||
if (f_err.path().isEmpty()) {
|
||||
f_err.openTemporary(PIIODevice::ReadWrite);
|
||||
t_err = true;
|
||||
}
|
||||
|
||||
str = args.front();
|
||||
is_exec = true;
|
||||
@@ -165,16 +206,21 @@ void PIProcess::startProc(bool detached) {
|
||||
if (!detached) PRIVATE->pid = pid_;
|
||||
if (pid_ == 0) {
|
||||
# endif
|
||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||
// cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
// cout << f_out.path() << endl;
|
||||
if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin);
|
||||
if (g_out) PRIVATE->tf_out = freopen(f_out.path().data(), "w", stdout);
|
||||
if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr);
|
||||
// PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||
// // cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
// // cout << f_out.path() << endl;
|
||||
// if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin);
|
||||
// if (g_out) PRIVATE->tf_out = freopen(f_out.path().data(), "w", stdout);
|
||||
// if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr);
|
||||
|
||||
# ifdef WINDOWS
|
||||
GetStartupInfoA(&(PRIVATE->si));
|
||||
piZeroMemory(PRIVATE->pi);
|
||||
STARTUPINFOA si;
|
||||
piZeroMemory(pi);
|
||||
si.cb = sizeof(STARTUPINFOA);
|
||||
if (PRIVATE->grab[StdFile::In]) si.hStdInput = PRIVATE->pipes[StdFile::In][PipeDirection::Read];
|
||||
if (PRIVATE->grab[StdFile::Out]) si.hStdOutput = PRIVATE->pipes[StdFile::Out][PipeDirection::Write];
|
||||
if (PRIVATE->grab[StdFile::Err]) si.hStdError = PRIVATE->pipes[StdFile::Err][PipeDirection::Write];
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
if (CreateProcessA(0, // No module name (use command line)
|
||||
a, // Command line
|
||||
0, // Process handle not inheritable
|
||||
@@ -183,7 +229,7 @@ void PIProcess::startProc(bool detached) {
|
||||
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
|
||||
0, // envcc, // Use environment
|
||||
wd.isEmpty() ? 0 : wd.data(), // Use working directory
|
||||
&(PRIVATE->si), // Pointer to STARTUPINFO structure
|
||||
&si, // Pointer to STARTUPINFO structure
|
||||
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
|
||||
{
|
||||
if (!detached) {
|
||||
@@ -223,21 +269,23 @@ void PIProcess::startProc(bool detached) {
|
||||
# endif
|
||||
}
|
||||
|
||||
PIByteArray PIProcess::readFile(PIFile & f, bool clear)
|
||||
{
|
||||
f.open(PIIODevice::ReadOnly);
|
||||
const auto ret = f.readAll();
|
||||
if (clear) {
|
||||
f.clear();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// PIByteArray PIProcess::readFile(PIFile & f, bool clear)
|
||||
// {
|
||||
// f.open(PIIODevice::ReadOnly);
|
||||
// const auto ret = f.readAll();
|
||||
// if (clear) {
|
||||
// f.clear();
|
||||
// }
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
|
||||
void PIProcess::terminate() {
|
||||
# ifdef WINDOWS
|
||||
if (is_exec)
|
||||
{
|
||||
if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return;
|
||||
}
|
||||
PRIVATE->pi.dwProcessId = 0;
|
||||
# else
|
||||
if (is_exec) kill(PRIVATE->pid, SIGKILL);
|
||||
@@ -266,12 +314,14 @@ int PIProcess::pID() const {
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIProcess::readOutput(bool clear) {
|
||||
return readFile(f_out, clear);
|
||||
return {}; //readFile(f_out, clear);
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIProcess::readError(bool clear) {
|
||||
return readFile(f_err, clear);
|
||||
return {}; //readFile(f_err, clear);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,36 +55,6 @@ public:
|
||||
//! \~russian Возвращает ID процесса текущего выполнения
|
||||
int pID() const;
|
||||
|
||||
void setGrabInput(bool yes) { g_in = yes; }
|
||||
|
||||
//! \~english Set attached execution grab output stream enabled
|
||||
//! \~russian
|
||||
void setGrabOutput(bool yes) { g_out = yes; }
|
||||
|
||||
//! \~english Set attached execution grab error stream enabled
|
||||
//! \~russian
|
||||
void setGrabError(bool yes) { g_err = yes; }
|
||||
|
||||
void setInputFile(const PIString & path) { f_in.setPath(path); }
|
||||
|
||||
//! \~english Set attached execution grab output stream file
|
||||
//! \~russian
|
||||
void setOutputFile(const PIString & path) { f_out.setPath(path); }
|
||||
|
||||
//! \~english Set attached execution grab error stream file
|
||||
//! \~russian
|
||||
void setErrorFile(const PIString & path) { f_err.setPath(path); }
|
||||
|
||||
void unsetInputFile() { f_in.setPath(""); }
|
||||
|
||||
//! \~english Reset attached execution grab output stream file
|
||||
//! \~russian
|
||||
void unsetOutputFile() { f_out.setPath(""); }
|
||||
|
||||
//! \~english Reset attached execution grab error stream file
|
||||
//! \~russian
|
||||
void unsetErrorFile() { f_err.setPath(""); }
|
||||
|
||||
//! \~english Returns current attached execution working directory or empty string if it wasn`t set
|
||||
//! \~russian
|
||||
PIString workingDirectory() const { return wd; }
|
||||
@@ -220,14 +190,11 @@ private:
|
||||
void run() override;
|
||||
void exec_();
|
||||
void startProc(bool detached);
|
||||
PIByteArray readFile(PIFile & f, bool clear);
|
||||
|
||||
private:
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
PIStringList args, env;
|
||||
PIString wd;
|
||||
PIByteArray out;
|
||||
PIFile f_in, f_out, f_err;
|
||||
bool g_in, g_out, g_err, t_in, t_out, t_err;
|
||||
int exit_code;
|
||||
bool is_exec;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user