+int wxAppTraits::AddProcessCallback(wxEndProcessData *data, int fd)
+{
+ // define a custom handler processing only the closure of the descriptor
+ struct wxEndProcessFDIOHandler : public wxFDIOHandler
+ {
+ wxEndProcessFDIOHandler(wxEndProcessData *data, int fd)
+ : m_data(data), m_fd(fd)
+ {
+ }
+
+ virtual void OnReadWaiting()
+ {
+ wxFDIODispatcher::Get()->UnregisterFD(m_fd);
+ close(m_fd);
+
+ wxHandleProcessTermination(m_data);
+
+ delete this;
+ }
+
+ virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); }
+ virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); }
+
+ wxEndProcessData * const m_data;
+ const int m_fd;
+ };
+
+ wxFDIODispatcher::Get()->RegisterFD
+ (
+ fd,
+ new wxEndProcessFDIOHandler(data, fd),
+ wxFDIO_INPUT
+ );
+ return fd; // unused, but return something unique for the tag
+}
+
+bool wxAppTraits::CheckForRedirectedIO(wxExecuteData& execData)
+{
+#if HAS_PIPE_STREAMS
+ bool hasIO = false;
+
+ if ( execData.bufOut && execData.bufOut->Update() )
+ hasIO = true;
+
+ if ( execData.bufErr && execData.bufErr->Update() )
+ hasIO = true;
+
+ return hasIO;
+#else // !HAS_PIPE_STREAMS
+ wxUnusedVar(execData);
+
+ return false;
+#endif // HAS_PIPE_STREAMS/!HAS_PIPE_STREAMS
+}
+
+// helper classes/functions used by WaitForChild()
+namespace
+{
+
+// convenient base class for IO handlers which are registered for read
+// notifications only and which also stores the FD we're reading from
+//
+// the derived classes still have to implement OnReadWaiting()
+class wxReadFDIOHandler : public wxFDIOHandler
+{
+public:
+ wxReadFDIOHandler(wxFDIODispatcher& disp, int fd) : m_fd(fd)
+ {
+ if ( fd )
+ disp.RegisterFD(fd, this, wxFDIO_INPUT);
+ }
+
+ virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); }
+ virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); }
+
+protected:
+ const int m_fd;
+
+ wxDECLARE_NO_COPY_CLASS(wxReadFDIOHandler);
+};
+
+// class for monitoring our end of the process detection pipe, simply sets a
+// flag when input on the pipe (which must be due to EOF) is detected
+class wxEndHandler : public wxReadFDIOHandler
+{
+public:
+ wxEndHandler(wxFDIODispatcher& disp, int fd)
+ : wxReadFDIOHandler(disp, fd)
+ {
+ m_terminated = false;
+ }
+
+ bool Terminated() const { return m_terminated; }
+
+ virtual void OnReadWaiting() { m_terminated = true; }
+
+private:
+ bool m_terminated;
+
+ wxDECLARE_NO_COPY_CLASS(wxEndHandler);
+};
+
+#if HAS_PIPE_STREAMS
+
+// class for monitoring our ends of child stdout/err, should be constructed
+// with the FD and stream from wxExecuteData and will do nothing if they're
+// invalid
+//
+// unlike wxEndHandler this class registers itself with the provided dispatcher
+class wxRedirectedIOHandler : public wxReadFDIOHandler
+{
+public:
+ wxRedirectedIOHandler(wxFDIODispatcher& disp,
+ int fd,
+ wxStreamTempInputBuffer *buf)
+ : wxReadFDIOHandler(disp, fd),
+ m_buf(buf)
+ {
+ }
+
+ virtual void OnReadWaiting()
+ {
+ m_buf->Update();
+ }
+
+private:
+ wxStreamTempInputBuffer * const m_buf;
+
+ wxDECLARE_NO_COPY_CLASS(wxRedirectedIOHandler);
+};
+
+#endif // HAS_PIPE_STREAMS
+
+// helper function which calls waitpid() and analyzes the result
+int DoWaitForChild(int pid, int flags = 0)