+ wxEndProcessData *endProcData = new wxEndProcessData;
+
+ const int flags = execData.flags;
+
+ // wxAddProcessCallback is now (with DARWIN) allowed to call the
+ // callback function directly if the process terminates before
+ // the callback can be added to the run loop. Set up the endProcData.
+ if ( flags & wxEXEC_SYNC )
+ {
+ // we may have process for capturing the program output, but it's
+ // not used in wxEndProcessData in the case of sync execution
+ endProcData->process = NULL;
+
+ // sync execution: indicate it by negating the pid
+ endProcData->pid = -execData.pid;
+ }
+ else
+ {
+ // async execution, nothing special to do -- caller will be
+ // notified about the process termination if process != NULL, endProcData
+ // will be deleted in GTK_EndProcessDetector
+ endProcData->process = execData.process;
+ endProcData->pid = execData.pid;
+ }
+
+
+ if ( !(flags & wxEXEC_NOEVENTS) )
+ {
+#if USE_OLD_DARWIN_END_PROCESS_DETECT
+ endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
+#else
+ endProcData->tag = wxAddProcessCallback
+ (
+ endProcData,
+ execData.pipeEndProcDetect.Detach(wxPipe::Read)
+ );
+
+ execData.pipeEndProcDetect.Close();
+#endif // USE_OLD_DARWIN_END_PROCESS_DETECT
+ }
+
+ if ( flags & wxEXEC_SYNC )
+ {
+ wxBusyCursor bc;
+ int exitcode = 0;
+
+ wxWindowDisabler *wd = flags & (wxEXEC_NODISABLE | wxEXEC_NOEVENTS)
+ ? NULL
+ : new wxWindowDisabler;
+
+ if ( flags & wxEXEC_NOEVENTS )
+ {
+ // just block waiting for the child to exit
+ int status = 0;
+
+ int result = waitpid(execData.pid, &status, 0);
+#ifdef __DARWIN__
+ /* DE: waitpid manpage states that waitpid can fail with EINTR
+ if the call is interrupted by a caught signal. I suppose
+ that means that this ought to be a while loop.
+
+ The odd thing is that it seems to fail EVERY time. It fails
+ with a quickly exiting process (e.g. echo), and fails with a
+ slowly exiting process (e.g. sleep 2) but clearly after
+ having waited for the child to exit. Maybe it's a bug in
+ my particular version.
+
+ It works, however, from the CFSocket callback without this
+ trick but in that case it's used only after CFSocket calls
+ the callback and with the WNOHANG flag which would seem to
+ preclude it from being interrupted or at least make it much
+ less likely since it would not then be waiting.
+
+ If Darwin's man page is to be believed then this is definitely
+ necessary. It's just weird that I've never seen it before
+ and apparently no one else has either or you'd think they'd
+ have reported it by now. Perhaps blocking the GUI while
+ waiting for a child process to exit is simply not that common.
+ */
+ if(result == -1 && errno == EINTR)
+ {
+ result = waitpid(execData.pid, &status, 0);
+ }
+
+#endif
+
+ if ( result == -1 )
+ {
+ wxLogLastError(_T("waitpid"));
+ exitcode = -1;
+ }
+ else
+ {
+ wxASSERT_MSG( result == execData.pid,
+ _T("unexpected waitpid() return value") );
+
+ if ( WIFEXITED(status) )
+ {
+ exitcode = WEXITSTATUS(status);
+ }
+ else // abnormal termination?
+ {
+ wxASSERT_MSG( WIFSIGNALED(status),
+ _T("unexpected child wait status") );
+ exitcode = -1;
+ }
+ }
+ }
+ else // !wxEXEC_NOEVENTS
+ {
+ // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
+ // process terminates
+ while ( endProcData->pid != 0 )
+ {
+ bool idle = true;
+
+#if HAS_PIPE_INPUT_STREAM
+ if ( execData.bufOut )
+ {
+ execData.bufOut->Update();
+ idle = false;
+ }
+
+ if ( execData.bufErr )
+ {
+ execData.bufErr->Update();
+ idle = false;
+ }
+#endif // HAS_PIPE_INPUT_STREAM
+
+ // don't consume 100% of the CPU while we're sitting in this
+ // loop
+ if ( idle )
+ wxMilliSleep(1);
+
+ // give GTK+ a chance to call GTK_EndProcessDetector here and
+ // also repaint the GUI
+ wxYield();
+ }
+
+ exitcode = endProcData->exitcode;
+ }
+
+ delete wd;
+ delete endProcData;
+
+ return exitcode;
+ }
+ else // async execution
+ {
+ return execData.pid;
+ }