summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-json-rpc-connection.h9
-rw-r--r--source/core/slang-http.cpp49
-rw-r--r--source/core/unix/slang-unix-process.cpp16
3 files changed, 66 insertions, 8 deletions
diff --git a/source/compiler-core/slang-json-rpc-connection.h b/source/compiler-core/slang-json-rpc-connection.h
index b566140ef..263baf799 100644
--- a/source/compiler-core/slang-json-rpc-connection.h
+++ b/source/compiler-core/slang-json-rpc-connection.h
@@ -130,8 +130,8 @@ public:
JSONRPCConnection():m_container(nullptr) {}
protected:
- RefPtr<Slang::Process> m_process; ///< Backing process (optional)
- RefPtr<Slang::HTTPPacketConnection> m_connection; ///< The underlying 'transport' connection, whilst HTTP currently doesn't have to be
+ RefPtr<Process> m_process; ///< Backing process (optional)
+ RefPtr<HTTPPacketConnection> m_connection; ///< The underlying 'transport' connection, whilst HTTP currently doesn't have to be
DiagnosticSink m_diagnosticSink; ///< Holds any diagnostics typically generated by parsing JSON, producing JSON from native types
@@ -140,10 +140,7 @@ protected:
JSONValue m_jsonRoot; ///< The root JSON value for the currently read message.
- /// Default timeout is 10 seconds
- Int m_timeOutInMs = 10 * 1000;
- /// Termination timeout
- Int m_terminationTimeOutInMs = 1 * 1000;
+ Int m_terminationTimeOutInMs = 1 * 1000; ///< Time to wait for termination response. Default is 1 second
};
// ---------------------------------------------------------------------------
diff --git a/source/core/slang-http.cpp b/source/core/slang-http.cpp
index 6a4bb4f92..bb5994635 100644
--- a/source/core/slang-http.cpp
+++ b/source/core/slang-http.cpp
@@ -287,6 +287,46 @@ SlangResult HTTPPacketConnection::update()
return m_readResult;
}
+
+namespace { // anonymous
+
+// Handles binary backoff like sleeping mechanism.
+struct SleepState
+{
+ void sleep()
+ {
+ Process::sleepCurrentThread(m_intervalInMs);
+ _update();
+ }
+ void reset()
+ {
+ m_intervalInMs = 0;
+ m_count = 0;
+ }
+ void _update()
+ {
+ const Int maxIntervalInMs = 32;
+ const Int initialCountThreshold = 4;
+
+ ++m_count;
+
+ const Int countThreshold = (m_intervalInMs == 0) ? initialCountThreshold : 1;
+
+ // If we hit the count change the interval
+ if (m_count >= countThreshold)
+ {
+ m_intervalInMs = (m_intervalInMs == 0) ? 1 : Math::Min(m_intervalInMs * 2, maxIntervalInMs);
+ // Reset the count
+ m_count = 0;
+ }
+ }
+
+ Int m_intervalInMs = 0;
+ Int m_count = 0;
+};
+
+} // anonymous
+
SlangResult HTTPPacketConnection::waitForResult(Int timeOutInMs)
{
m_readResult = SLANG_OK;
@@ -300,6 +340,8 @@ SlangResult HTTPPacketConnection::waitForResult(Int timeOutInMs)
startTick = Process::getClockTick();
}
+ SleepState sleepState;
+
while (m_readState == ReadState::Header ||
m_readState == ReadState::Content)
{
@@ -320,8 +362,11 @@ SlangResult HTTPPacketConnection::waitForResult(Int timeOutInMs)
if (prevCount == m_readStream->getCount())
{
- // Yield if it appears nothing was read.
- Process::sleepCurrentThread(0);
+ sleepState.sleep();
+ }
+ else
+ {
+ sleepState.reset();
}
}
diff --git a/source/core/unix/slang-unix-process.cpp b/source/core/unix/slang-unix-process.cpp
index 5131e37ec..4e8344486 100644
--- a/source/core/unix/slang-unix-process.cpp
+++ b/source/core/unix/slang-unix-process.cpp
@@ -349,6 +349,8 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
return StringEscapeUtil::getHandler(StringEscapeUtil::Style::Space);
}
+static const int kCannotExecute = 126;
+
/* static */SlangResult Process::create(const CommandLine& commandLine, Process::Flags flags, RefPtr<Process>& outProcess)
{
List<char const*> argPtrs;
@@ -376,6 +378,12 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
return SLANG_FAIL;
}
+ // TODO(JS):
+ // Ideally we'd have a mechanism to test if execvp can be successfully executed (at least in principal) before
+ // doing fork. Once we have forked we then have the problem of communicating to the parent process somehow.
+ //
+ // We could do a search down PATH and test files etc, but this seems to repeat a lot of the functionality of exec.
+ //
pid_t childPid = fork();
if (childPid == -1)
{
@@ -402,6 +410,11 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
::close(stdinPipe[0]);
::close(stdinPipe[1]);
+ // TODO(JS): Strictly speaking if m_executableType is 'Path' then we shouldn't be searching. Ie which
+ // exec we use here should be dependent on the executable type.
+
+ // Path = execvp
+ // Filename = execv
::execvp(argPtrs[0], (char* const*)&argPtrs[0]);
// If we get here, then `exec` failed
@@ -410,6 +423,9 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
// the terminal but in the stderrPipe.
fprintf(stderr, "error: `exec` failed\n");
+ // Terminate with failure.
+ exit(kCannotExecute);
+
return SLANG_FAIL;
}
else