OK I think this fixes all the issues for me. However IMO getExitCode()
should also block until the process is finished, but I didn’t want to change the general behaviour of the existing code for now.
diff --git a/modules/juce_core/native/juce_posix_SharedCode.h b/modules/juce_core/native/juce_posix_SharedCode.h
index 7d4b91a..30284a0 100644
--- a/modules/juce_core/native/juce_posix_SharedCode.h
+++ b/modules/juce_core/native/juce_posix_SharedCode.h
@@ -1123,11 +1123,12 @@ static inline String readPosixConfigFileValue (const char* file, const char* con
//==============================================================================
-class ChildProcess::ActiveProcess
+ class ChildProcess::ActiveProcess : private Thread
{
public:
ActiveProcess (const StringArray& arguments, int streamFlags)
- : childPID (0), pipeHandle (0), readHandle (0)
+ : Thread (arguments[0].unquoted())
+ , childPID (0), pipeHandle (0), readHandle (0)
{
String exe (arguments[0].unquoted());
@@ -1181,26 +1182,37 @@ public:
pipeHandle = pipeHandles[0];
close (pipeHandles[1]); // close the write handle
}
- }
+ }
+
+ startThread();
}
~ActiveProcess()
- {
+ {
+ stopThread (1000);
+
if (readHandle != 0)
fclose (readHandle);
if (pipeHandle != 0)
close (pipeHandle);
+ }
+
+ void run() override
+ {
+ while (pid == 0 && ! threadShouldExit())
+ {
+ pid = waitpid (childPID, &childState, WNOHANG);
+
+ if (pid == 0)
+ Thread::yield();
+ }
}
bool isRunning() const noexcept
{
if (childPID != 0)
- {
- int childState;
- const int pid = waitpid (childPID, &childState, WNOHANG);
return pid == 0 || ! (WIFEXITED (childState) || WIFSIGNALED (childState));
- }
return false;
}
@@ -1213,8 +1225,8 @@ public:
#error // the zlib headers define this function as NULL!
#endif
- if (readHandle == 0 && childPID != 0)
- readHandle = fdopen (pipeHandle, "r");
+ if (readHandle == 0 && childPID != 0)
+ do { readHandle = fdopen (pipeHandle, "r"); } while (readHandle == 0);
if (readHandle != 0)
return (int) fread (dest, 1, (size_t) numBytes, readHandle);
@@ -1227,23 +1239,27 @@ public:
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;
+ uint32 getExitCode() const noexcept
+ {
+ if (childPID != 0)
+ {
+ if (WIFEXITED (childState))
+ return WEXITSTATUS (childState);
+ }
+
+ return 0;
}
int childPID;
-private:
+private:
+ int pid = 0;
+ int childState = 0;
int pipeHandle;
FILE* readHandle;
Basically what’s happening above is ActiveProcess is inheriting from Thread, in it’s run()
function it is running a loop to determine the returned pid
and childState
values and store them in member variables. Then everywhere that previously had a local pid
or childState
value was replaced to use the member variables.
The other fix applied was in read()
, I changed…
if (readHandle == 0 && childPID != 0)
readHandle = fdopen (pipeHandle, "r");
to this…
if (readHandle == 0 && childPID != 0)
do { readHandle = fdopen (pipeHandle, "r"); } while (readHandle == 0);
This is what stops the output being empty.