+ // Setup the signal handler for SIGCHLD to be able to detect the child
+ // termination.
+ //
+ // Notice that SetSignalHandler() is idempotent, so it's fine to call
+ // it more than once with the same handler.
+ wxTheApp->SetSignalHandler(SIGCHLD, OnSomeChildExited);
+
+
+ // Remember the child PID to be able to wait for it later.
+ pid = pid_;
+
+ // Also save it in wxProcess where it will be accessible to the user code.
+ if ( process )
+ process->SetPid(pid);
+
+ // Finally, add this object itself to the list of child processes so that
+ // we can check for its termination the next time we get SIGCHLD.
+ ms_childProcesses[pid] = this;
+}
+
+void wxExecuteData::OnExit(int exitcode_)
+{
+ // Remove this process from the hash list of child processes that are
+ // still open as soon as possible to ensure we don't process it again even
+ // if another SIGCHLD happens.
+ if ( !ms_childProcesses.erase(pid) )
+ {
+ wxFAIL_MSG(wxString::Format(wxS("Data for PID %d not in the list?"), pid));
+ }
+
+
+ exitcode = exitcode_;
+
+#if wxUSE_STREAMS
+ if ( IsRedirected() )
+ {
+ // Read the remaining data in a blocking way: this is fine because the
+ // child has already exited and hence all the data must be already
+ // available in the streams buffers.
+ bufOut.ReadAll();
+ bufErr.ReadAll();
+ }
+#endif // wxUSE_STREAMS
+
+ // Notify user about termination if required
+ if ( !(flags & wxEXEC_SYNC) )
+ {
+ if ( process )
+ process->OnTerminate(pid, exitcode);
+
+ // in case of asynchronous execution we don't need this object any more
+ // after the child terminates
+ delete this;
+ }
+ else // sync execution
+ {
+ // let wxExecute() know that the process has terminated
+ pid = 0;
+
+ // Stop the event loop for synchronous wxExecute() if we're running one.
+ if ( syncEventLoop )
+ syncEventLoop->ScheduleExit();
+ }
+}