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)
|
PRIVATE_DEFINITION_START(PIProcess)
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
STARTUPINFOA si;
|
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
# else
|
# else
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
# endif
|
# 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)
|
PRIVATE_DEFINITION_END(PIProcess)
|
||||||
|
|
||||||
|
|
||||||
@@ -82,18 +140,14 @@ PIProcess::PIProcess(): PIThread() {
|
|||||||
PRIVATE->pid = 0;
|
PRIVATE->pid = 0;
|
||||||
# endif
|
# endif
|
||||||
is_exec = false;
|
is_exec = false;
|
||||||
g_in = g_out = g_err = false;
|
PRIVATE->forEachPipe([](PipeHandleType & pipe) { pipe = 0;});
|
||||||
t_in = t_out = t_err = false;
|
PRIVATE->initGrab();
|
||||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
env = PIProcess::currentEnvironment();
|
||||||
env = PIProcess::currentEnvironment();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIProcess::~PIProcess() {
|
PIProcess::~PIProcess() {
|
||||||
PIThread::stopAndWait();
|
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
|
# endif
|
||||||
/// files for stdin/out/err
|
/// 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();
|
str = args.front();
|
||||||
is_exec = true;
|
is_exec = true;
|
||||||
@@ -165,16 +206,21 @@ void PIProcess::startProc(bool detached) {
|
|||||||
if (!detached) PRIVATE->pid = pid_;
|
if (!detached) PRIVATE->pid = pid_;
|
||||||
if (pid_ == 0) {
|
if (pid_ == 0) {
|
||||||
# endif
|
# endif
|
||||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
// PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||||
// cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
// // cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||||
// cout << f_out.path() << endl;
|
// // cout << f_out.path() << endl;
|
||||||
if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin);
|
// 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_out) PRIVATE->tf_out = freopen(f_out.path().data(), "w", stdout);
|
||||||
if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr);
|
// if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr);
|
||||||
|
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
GetStartupInfoA(&(PRIVATE->si));
|
STARTUPINFOA si;
|
||||||
piZeroMemory(PRIVATE->pi);
|
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)
|
if (CreateProcessA(0, // No module name (use command line)
|
||||||
a, // Command line
|
a, // Command line
|
||||||
0, // Process handle not inheritable
|
0, // Process handle not inheritable
|
||||||
@@ -183,7 +229,7 @@ void PIProcess::startProc(bool detached) {
|
|||||||
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
|
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
|
||||||
0, // envcc, // Use environment
|
0, // envcc, // Use environment
|
||||||
wd.isEmpty() ? 0 : wd.data(), // Use working directory
|
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
|
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
|
||||||
{
|
{
|
||||||
if (!detached) {
|
if (!detached) {
|
||||||
@@ -223,21 +269,23 @@ void PIProcess::startProc(bool detached) {
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PIByteArray PIProcess::readFile(PIFile & f, bool clear)
|
// PIByteArray PIProcess::readFile(PIFile & f, bool clear)
|
||||||
{
|
// {
|
||||||
f.open(PIIODevice::ReadOnly);
|
// f.open(PIIODevice::ReadOnly);
|
||||||
const auto ret = f.readAll();
|
// const auto ret = f.readAll();
|
||||||
if (clear) {
|
// if (clear) {
|
||||||
f.clear();
|
// f.clear();
|
||||||
}
|
// }
|
||||||
return ret;
|
// return ret;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
void PIProcess::terminate() {
|
void PIProcess::terminate() {
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
if (is_exec)
|
if (is_exec)
|
||||||
|
{
|
||||||
if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return;
|
if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return;
|
||||||
|
}
|
||||||
PRIVATE->pi.dwProcessId = 0;
|
PRIVATE->pi.dwProcessId = 0;
|
||||||
# else
|
# else
|
||||||
if (is_exec) kill(PRIVATE->pid, SIGKILL);
|
if (is_exec) kill(PRIVATE->pid, SIGKILL);
|
||||||
@@ -266,12 +314,14 @@ int PIProcess::pID() const {
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIByteArray PIProcess::readOutput(bool clear) {
|
PIByteArray PIProcess::readOutput(bool clear) {
|
||||||
return readFile(f_out, clear);
|
return {}; //readFile(f_out, clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIByteArray PIProcess::readError(bool clear) {
|
PIByteArray PIProcess::readError(bool clear) {
|
||||||
return readFile(f_err, clear);
|
return {}; //readFile(f_err, clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,36 +55,6 @@ public:
|
|||||||
//! \~russian Возвращает ID процесса текущего выполнения
|
//! \~russian Возвращает ID процесса текущего выполнения
|
||||||
int pID() const;
|
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
|
//! \~english Returns current attached execution working directory or empty string if it wasn`t set
|
||||||
//! \~russian
|
//! \~russian
|
||||||
PIString workingDirectory() const { return wd; }
|
PIString workingDirectory() const { return wd; }
|
||||||
@@ -220,14 +190,11 @@ private:
|
|||||||
void run() override;
|
void run() override;
|
||||||
void exec_();
|
void exec_();
|
||||||
void startProc(bool detached);
|
void startProc(bool detached);
|
||||||
PIByteArray readFile(PIFile & f, bool clear);
|
|
||||||
|
|
||||||
|
private:
|
||||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||||
PIStringList args, env;
|
PIStringList args, env;
|
||||||
PIString wd;
|
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;
|
int exit_code;
|
||||||
bool is_exec;
|
bool is_exec;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user