-        // 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 // __DARWIN__
+        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;
+
+    DECLARE_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;
+
+    DECLARE_NO_COPY_CLASS(wxEndHandler)
+};
+
+#if wxUSE_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;
+
+    DECLARE_NO_COPY_CLASS(wxRedirectedIOHandler)
+};