| @@ -151,7 +151,6 @@ namespace juce | |||
| #include "text/juce_StringPairArray.cpp" | |||
| #include "text/juce_StringPool.cpp" | |||
| #include "text/juce_TextDiff.cpp" | |||
| #include "threads/juce_ChildProcess.cpp" | |||
| #include "threads/juce_ReadWriteLock.cpp" | |||
| #include "threads/juce_Thread.cpp" | |||
| #include "threads/juce_ThreadPool.cpp" | |||
| @@ -218,6 +217,7 @@ namespace juce | |||
| #endif | |||
| #include "threads/juce_ChildProcess.cpp" | |||
| #include "threads/juce_HighResolutionTimer.cpp" | |||
| } | |||
| @@ -1053,7 +1053,7 @@ public: | |||
| close (pipeHandle); | |||
| } | |||
| bool isRunning() const | |||
| bool isRunning() const noexcept | |||
| { | |||
| if (childPID != 0) | |||
| { | |||
| @@ -1065,7 +1065,7 @@ public: | |||
| return false; | |||
| } | |||
| int read (void* const dest, const int numBytes) | |||
| int read (void* const dest, const int numBytes) noexcept | |||
| { | |||
| jassert (dest != nullptr); | |||
| @@ -1082,11 +1082,25 @@ public: | |||
| return 0; | |||
| } | |||
| bool killProcess() const | |||
| bool killProcess() const noexcept | |||
| { | |||
| return ::kill (childPID, SIGKILL) == 0; | |||
| } | |||
| uint32 getExitCode() const noexcept | |||
| { | |||
| if (childPID != 0) | |||
| { | |||
| int childState = 0; | |||
| const int pid = waitpid (childPID, &childState, WNOHANG); | |||
| if (pid >= 0 && WIFEXITED (childState)) | |||
| return WEXITSTATUS (childState); | |||
| } | |||
| return 0; | |||
| } | |||
| int childPID; | |||
| private: | |||
| @@ -1114,21 +1128,6 @@ bool ChildProcess::start (const StringArray& args, int streamFlags) | |||
| return activeProcess != nullptr; | |||
| } | |||
| bool ChildProcess::isRunning() const | |||
| { | |||
| return activeProcess != nullptr && activeProcess->isRunning(); | |||
| } | |||
| int ChildProcess::readProcessOutput (void* dest, int numBytes) | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; | |||
| } | |||
| bool ChildProcess::kill() | |||
| { | |||
| return activeProcess == nullptr || activeProcess->killProcess(); | |||
| } | |||
| //============================================================================== | |||
| struct HighResolutionTimer::Pimpl | |||
| { | |||
| @@ -482,12 +482,12 @@ public: | |||
| CloseHandle (writePipe); | |||
| } | |||
| bool isRunning() const | |||
| bool isRunning() const noexcept | |||
| { | |||
| return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0; | |||
| } | |||
| int read (void* dest, int numNeeded) const | |||
| int read (void* dest, int numNeeded) const noexcept | |||
| { | |||
| int total = 0; | |||
| @@ -522,11 +522,18 @@ public: | |||
| return total; | |||
| } | |||
| bool killProcess() const | |||
| bool killProcess() const noexcept | |||
| { | |||
| return TerminateProcess (processInfo.hProcess, 0) != FALSE; | |||
| } | |||
| uint32 getExitCode() const noexcept | |||
| { | |||
| DWORD exitCode = 0; | |||
| GetExitCodeProcess (processInfo.hProcess, &exitCode); | |||
| return (uint32) exitCode; | |||
| } | |||
| bool ok; | |||
| private: | |||
| @@ -551,21 +558,6 @@ bool ChildProcess::start (const StringArray& args, int streamFlags) | |||
| return start (args.joinIntoString (" "), streamFlags); | |||
| } | |||
| bool ChildProcess::isRunning() const | |||
| { | |||
| return activeProcess != nullptr && activeProcess->isRunning(); | |||
| } | |||
| int ChildProcess::readProcessOutput (void* dest, int numBytes) | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; | |||
| } | |||
| bool ChildProcess::kill() | |||
| { | |||
| return activeProcess == nullptr || activeProcess->killProcess(); | |||
| } | |||
| //============================================================================== | |||
| struct HighResolutionTimer::Pimpl | |||
| { | |||
| @@ -29,6 +29,26 @@ | |||
| ChildProcess::ChildProcess() {} | |||
| ChildProcess::~ChildProcess() {} | |||
| bool ChildProcess::isRunning() const | |||
| { | |||
| return activeProcess != nullptr && activeProcess->isRunning(); | |||
| } | |||
| int ChildProcess::readProcessOutput (void* dest, int numBytes) | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; | |||
| } | |||
| bool ChildProcess::kill() | |||
| { | |||
| return activeProcess == nullptr || activeProcess->killProcess(); | |||
| } | |||
| uint32 ChildProcess::getExitCode() const | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->getExitCode() : 0; | |||
| } | |||
| bool ChildProcess::waitForProcessToFinish (const int timeoutMs) const | |||
| { | |||
| const uint32 timeoutTime = Time::getMillisecondCounter() + (uint32) timeoutMs; | |||
| @@ -97,6 +97,9 @@ public: | |||
| /** Blocks until the process is no longer running. */ | |||
| bool waitForProcessToFinish (int timeoutMs) const; | |||
| /** If the process has finished, this returns its exit code. */ | |||
| uint32 getExitCode() const; | |||
| /** Attempts to kill the child process. | |||
| Returns true if it succeeded. Trying to read from the process after calling this may | |||
| result in undefined behaviour. | |||