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

View File

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