+ // It is possible that wxExecuteData::OnExit() had already been called
+ // and reset the PID to 0, in which case we don't need to do anything
+ // at all.
+ if ( !execData.pid )
+ return execData.exitcode;
+
+#if wxUSE_STREAMS
+ // Monitor the child streams if necessary.
+ wxScopedPtr<wxEventLoopSourceHandler>
+ stdoutHandler,
+ stderrHandler;
+ if ( execData.IsRedirected() )
+ {
+ stdoutHandler.reset(new wxExecuteEventLoopSourceHandler
+ (
+ execData.fdOut, execData.bufOut
+ ));
+ stderrHandler.reset(new wxExecuteEventLoopSourceHandler
+ (
+ execData.fdErr, execData.bufErr
+ ));
+ }
+#endif // wxUSE_STREAMS
+
+ // Store the event loop in the data associated with the child
+ // process so that it could exit the loop when the child exits.
+ execData.syncEventLoop = &loop;
+
+ // And run it.
+ loop.Run();
+
+ // The exit code will have been set when the child termination was detected.
+ return execData.exitcode;
+}
+
+// ----------------------------------------------------------------------------
+// wxExecuteData
+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+// Helper function that checks whether the child with the given PID has exited
+// and fills the provided parameter with its return code if it did.
+bool CheckForChildExit(int pid, int* exitcodeOut)
+{
+ wxASSERT_MSG( pid > 0, "invalid PID" );
+
+ int status, rc;
+
+ // loop while we're getting EINTR
+ for ( ;; )
+ {
+ rc = waitpid(pid, &status, WNOHANG);
+
+ if ( rc != -1 || errno != EINTR )
+ break;
+ }
+
+ switch ( rc )
+ {
+ case 0:
+ // No error but the child is still running.
+ return false;
+
+ case -1:
+ // Checking child status failed. Invalid PID?
+ wxLogLastError(wxString::Format("waitpid(%d)", pid));
+ return false;
+
+ default:
+ // Child did terminate.
+ wxASSERT_MSG( rc == pid, "unexpected waitpid() return value" );
+
+ // notice that the caller expects the exit code to be signed, e.g. -1
+ // instead of 255 so don't assign WEXITSTATUS() to an int
+ signed char exitcode;
+ if ( WIFEXITED(status) )
+ exitcode = WEXITSTATUS(status);
+ else if ( WIFSIGNALED(status) )
+ exitcode = -WTERMSIG(status);
+ else
+ {
+ wxLogError("Child process (PID %d) exited for unknown reason, "
+ "status = %d", pid, status);
+ exitcode = -1;
+ }
+
+ if ( exitcodeOut )
+ *exitcodeOut = exitcode;
+
+ return true;
+ }