starting pipes

This commit is contained in:
2025-08-12 21:44:50 +03:00
parent 91955d44fa
commit 6ffbbbe636
2 changed files with 93 additions and 76 deletions

View File

@@ -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);
} }

View File

@@ -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;
}; };