+namespace
+{
+
+// Helper function of wxExecute(): wait for the process termination without
+// dispatching any events.
+//
+// This is used in wxEXEC_NOEVENTS case.
+int BlockUntilChildExit(wxExecuteData& execData)
+{
+ wxCHECK_MSG( wxTheApp, -1,
+ wxS("Can't block until child exit without wxTheApp") );
+
+ // Even if we don't want to dispatch events, we still need to handle
+ // child IO notifications and process termination concurrently, i.e.
+ // we can't simply block waiting for the child to terminate as we would
+ // dead lock if it writes more than the pipe buffer size (typically
+ // 4KB) bytes of output -- it would then block waiting for us to read
+ // the data while we'd block waiting for it to terminate.
+ //
+ // So while we don't use the full blown event loop, we still do use a
+ // dispatcher with which we register just the 3 FDs we're interested
+ // in: the child stdout and stderr and the pipe written to by the
+ // signal handler so that we could react to the child process
+ // termination too.
+
+ // Notice that we must create a new dispatcher object here instead of
+ // reusing the global wxFDIODispatcher::Get() because we want to
+ // monitor only the events on the FDs explicitly registered with this
+ // one and not all the other ones that could be registered with the
+ // global dispatcher (think about the case of nested wxExecute() calls).
+ wxSelectDispatcher dispatcher;
+
+ // Do register all the FDs we want to monitor here: first, the one used to
+ // handle the signals asynchronously.
+ wxScopedPtr<wxFDIOHandler>
+ signalHandler(wxTheApp->RegisterSignalWakeUpPipe(dispatcher));
+
+#if wxUSE_STREAMS
+ // And then the two for the child output and error streams if necessary.
+ wxScopedPtr<wxFDIOHandler>
+ stdoutHandler,
+ stderrHandler;
+ if ( execData.IsRedirected() )
+ {
+ stdoutHandler.reset(new wxExecuteFDIOHandler
+ (
+ dispatcher,
+ execData.fdOut,
+ execData.bufOut
+ ));
+ stderrHandler.reset(new wxExecuteFDIOHandler
+ (
+ dispatcher,
+ execData.fdErr,
+ execData.bufErr
+ ));
+ }
+#endif // wxUSE_STREAMS
+
+ // And dispatch until the PID is reset from wxExecuteData::OnExit().
+ while ( execData.pid )
+ {
+ dispatcher.Dispatch();
+ }
+
+ return execData.exitcode;
+}
+
+} // anonymous namespace
+