diff --git a/modules/juce_core/juce_core.cpp b/modules/juce_core/juce_core.cpp index 8288e91a5a..be6b6ebf5c 100644 --- a/modules/juce_core/juce_core.cpp +++ b/modules/juce_core/juce_core.cpp @@ -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" } diff --git a/modules/juce_core/native/juce_posix_SharedCode.h b/modules/juce_core/native/juce_posix_SharedCode.h index 46d2382d68..402662a153 100644 --- a/modules/juce_core/native/juce_posix_SharedCode.h +++ b/modules/juce_core/native/juce_posix_SharedCode.h @@ -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 { diff --git a/modules/juce_core/native/juce_win32_Threads.cpp b/modules/juce_core/native/juce_win32_Threads.cpp index d6de0f804f..4537bce8b6 100644 --- a/modules/juce_core/native/juce_win32_Threads.cpp +++ b/modules/juce_core/native/juce_win32_Threads.cpp @@ -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 { diff --git a/modules/juce_core/threads/juce_ChildProcess.cpp b/modules/juce_core/threads/juce_ChildProcess.cpp index 7edab2a5fc..4566b13f1d 100644 --- a/modules/juce_core/threads/juce_ChildProcess.cpp +++ b/modules/juce_core/threads/juce_ChildProcess.cpp @@ -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; diff --git a/modules/juce_core/threads/juce_ChildProcess.h b/modules/juce_core/threads/juce_ChildProcess.h index c5a245ff27..0adcb57b70 100644 --- a/modules/juce_core/threads/juce_ChildProcess.h +++ b/modules/juce_core/threads/juce_ChildProcess.h @@ -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.