summaryrefslogtreecommitdiffstats
path: root/source/core/slang-process-util.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2021-11-10 17:33:22 -0500
committerGitHub <noreply@github.com>2021-11-10 17:33:22 -0500
commit8a9e518371df03b3f382e0fe869da83751fdda0b (patch)
tree749f9c1c79acd375ec3ee97e45a10007dd6632fa /source/core/slang-process-util.cpp
parent95e82acc0b32c81a9c6ac39708d18a423d8c7b1e (diff)
Interprocess communication via pipes (#2009)
* #include an absolute path didn't work - because paths were taken to always be relative. * Use 'Process' to communicate with an command line tool. * Remove slang-win-stream * Tidy up windows ProcessUtil. * First version of BufferedReadStream. * Windows working IPC for steams. * Test proxy count option. * Split Process/ProcessUtil. Process is platform dependant. ProcessUtil are functions that are platform independent. * First implementation of Unix Process interface. * Unix process compiles on cygwin. * Fix typo in unix process. * Separate unix pipe stream error of invalid access, from pipe availability. * Fix in standard line extraction. * Make fd non blocking. * Fix issues with Windows Process streams. * Added UnixPipe. * Some fixes around UnixPipeStream. * Make a unix stream closed explicit. * Hack to debug linux process/stream. * Revert to old linux pipe handling. * Pass executable path for unit tests. Split out CommandLine into own source. * Small improvements in process/command line. * Check process behavior with crash. * Make stderr and stdout unbuffered for crash testing. * Only turn disable buffering in crash test. * Disable crash test on CI. * Fix crash on clang/linux. * Enable crash test. Remove _appendBuffer as can use StreamUtil functionality.
Diffstat (limited to 'source/core/slang-process-util.cpp')
-rw-r--r--source/core/slang-process-util.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/source/core/slang-process-util.cpp b/source/core/slang-process-util.cpp
new file mode 100644
index 000000000..b1466d150
--- /dev/null
+++ b/source/core/slang-process-util.cpp
@@ -0,0 +1,78 @@
+// slang-process-util.cpp
+
+#include "slang-process-util.h"
+
+#include "slang-string.h"
+#include "slang-string-escape-util.h"
+#include "slang-string-util.h"
+
+#include "../../slang-com-helper.h"
+
+namespace Slang {
+
+/* static */SlangResult ProcessUtil::execute(const CommandLine& commandLine, ExecuteResult& outExecuteResult)
+{
+ RefPtr<Process> process;
+ SLANG_RETURN_ON_FAIL(Process::create(commandLine, 0, process));
+ SLANG_RETURN_ON_FAIL(readUntilTermination(process, outExecuteResult));
+ return SLANG_OK;
+}
+
+static Index _getCount(List<Byte>* buf)
+{
+ return buf ? buf->getCount() : 0;
+}
+
+// We may want something more sophisticated here, if bytes is something other than ascii/utf8
+static String _getText(const ConstArrayView<Byte>& bytes)
+{
+ StringBuilder buf;
+ StringUtil::appendStandardLines(UnownedStringSlice((const char*)bytes.begin(), (const char*)bytes.end()), buf);
+ return buf.ProduceString();
+}
+
+/* static */SlangResult ProcessUtil::readUntilTermination(Process* process, ExecuteResult& outExecuteResult)
+{
+ List<Byte> stdOut;
+ List<Byte> stdError;
+
+ SLANG_RETURN_ON_FAIL(readUntilTermination(process, &stdOut, &stdError));
+
+ // Get the return code
+ outExecuteResult.resultCode = ExecuteResult::ResultCode(process->getReturnValue());
+
+ outExecuteResult.standardOutput = _getText(stdOut.getArrayView());
+ outExecuteResult.standardError = _getText(stdError.getArrayView());
+
+ return SLANG_OK;
+}
+
+/* static */SlangResult ProcessUtil::readUntilTermination(Process* process, List<Byte>* outStdOut, List<Byte>* outStdError)
+{
+ Stream* stdOutStream = process->getStream(Process::StreamType::StdOut);
+ Stream* stdErrorStream = process->getStream(Process::StreamType::ErrorOut);
+
+ while (!process->isTerminated())
+ {
+ const auto preCount = _getCount(outStdOut) + _getCount(outStdError);
+
+ SLANG_RETURN_ON_FAIL(StreamUtil::readOrDiscard(stdOutStream, 0, outStdOut));
+ SLANG_RETURN_ON_FAIL(StreamUtil::readOrDiscard(stdErrorStream, 0, outStdError));
+
+ const auto postCount = _getCount(outStdOut) + _getCount(outStdError);
+
+ // If nothing was read, we can yield
+ if (preCount == postCount)
+ {
+ Process::sleepCurrentThread(0);
+ }
+ }
+
+ // Read anything remaining
+ SLANG_RETURN_ON_FAIL(StreamUtil::readOrDiscardAll(stdOutStream, 0, outStdOut));
+ SLANG_RETURN_ON_FAIL(StreamUtil::readOrDiscardAll(stdErrorStream, 0, outStdError));
+
+ return SLANG_OK;
+}
+
+} // namespace Slang