diff --git a/libs/main/system/piprocess.cpp b/libs/main/system/piprocess.cpp index cedd417e..129063dd 100644 --- a/libs/main/system/piprocess.cpp +++ b/libs/main/system/piprocess.cpp @@ -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(PipeDirection::Last) + 1; +constexpr int StdFileCount = static_cast(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 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(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); } diff --git a/libs/main/system/piprocess.h b/libs/main/system/piprocess.h index 419776ee..e82b03d5 100644 --- a/libs/main/system/piprocess.h +++ b/libs/main/system/piprocess.h @@ -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; };