summaryrefslogtreecommitdiff
path: root/source/core/unix
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/unix')
-rw-r--r--source/core/unix/slang-unix-process.cpp72
1 files changed, 67 insertions, 5 deletions
diff --git a/source/core/unix/slang-unix-process.cpp b/source/core/unix/slang-unix-process.cpp
index 083160f02..5131e37ec 100644
--- a/source/core/unix/slang-unix-process.cpp
+++ b/source/core/unix/slang-unix-process.cpp
@@ -28,7 +28,9 @@ class UnixProcess : public Process
public:
// Process
virtual bool isTerminated() SLANG_OVERRIDE;
- virtual void waitForTermination() SLANG_OVERRIDE;
+ virtual bool waitForTermination(Int timeInMs) SLANG_OVERRIDE;
+ virtual void terminate(int32_t returnValue) SLANG_OVERRIDE;
+ virtual void kill(int32_t returnValue) SLANG_OVERRIDE;
UnixProcess(pid_t pid, Stream*const* streams);
@@ -133,9 +135,64 @@ bool UnixProcess::isTerminated()
return _updateTerminationState(WNOHANG);
}
-void UnixProcess::waitForTermination()
+bool UnixProcess::waitForTermination(Int timeInMs)
{
- while (!_updateTerminationState(0));
+ // If < 0 we will wait blocking until terminated
+ if (timeInMs < 0)
+ {
+ while (!_updateTerminationState(0));
+ return true;
+ }
+
+ // Note that the amount of time waiting is very approximate (we are relying on sleeps time and don't take into
+ // account time outside of sleeping)
+
+ // How often to test
+ const Int checkRateMs = 100; /// Check every 0.1 seconds
+
+ while (timeInMs > 0)
+ {
+ if (_updateTerminationState(WNOHANG))
+ {
+ return true;
+ }
+
+ // Work out how long to sleep for
+ const Int sleepMs = (timeInMs >= checkRateMs) ? checkRateMs : timeInMs;
+
+ // Sleep
+ sleepCurrentThread(sleepMs);
+
+ timeInMs -= sleepMs;
+ }
+
+ return _updateTerminationState(WNOHANG);
+}
+
+void UnixProcess::terminate(int32_t returnValue)
+{
+ // Using this mechanism, we can't set a returnValue so just ignore
+ SLANG_UNUSED(returnValue);
+
+ if (!isTerminated())
+ {
+ // Request the process terminates
+ ::kill(m_pid, SIGTERM);
+ }
+}
+
+void UnixProcess::kill(int32_t returnValue)
+{
+ if (!isTerminated())
+ {
+ // We waited, lets just terminate with kill
+ ::kill(m_pid, SIGKILL);
+
+ // Set the return value
+ m_returnValue = returnValue;
+ // Mark as terminated
+ m_isTerminated = true;
+ }
}
/* !!!!!!!!!!!!!!!!!!!!!! UnixPipeStream !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -386,15 +443,20 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
return uint64_t(now.tv_sec) * 1000000000 + now.tv_nsec;
}
-/* static */void Process::sleepCurrentThread(Index timeInMs)
+/* static */void Process::sleepCurrentThread(Int timeInMs)
{
struct timespec timeSpec;
- if (timeInMs > 0)
+ if (timeInMs >= 1000)
{
timeSpec.tv_sec = timeInMs / 1000;
timeSpec.tv_nsec = (timeInMs % 1000) * 1000 * 1000;
}
+ else if (timeInMs > 0)
+ {
+ timeSpec.tv_sec = 0;
+ timeSpec.tv_nsec = timeInMs * 1000 * 1000;
+ }
else
{
timeSpec.tv_sec = 0;