X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b477f956e0421cb8d8e40635f4c372a0298fd739..3cd94a0d119ade811cd876a309cfe6d28b5c36dd:/src/unix/utilsunx.cpp diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 94da23f516..c7f527e9b2 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -26,7 +26,7 @@ #include "wx/process.h" #include "wx/thread.h" -#include "wx/stream.h" +#include "wx/wfstream.h" #ifdef HAVE_STATFS # ifdef __BSD__ @@ -349,35 +349,20 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) #if wxUSE_STREAMS -class wxProcessFileInputStream : public wxInputStream -{ -public: - wxProcessFileInputStream(int fd) { m_fd = fd; } - ~wxProcessFileInputStream() { close(m_fd); } - - virtual bool Eof() const; - -protected: - size_t OnSysRead(void *buffer, size_t bufsize); - -protected: - int m_fd; -}; +// ---------------------------------------------------------------------------- +// wxProcessFileInputStream: stream for reading from a pipe +// ---------------------------------------------------------------------------- -class wxProcessFileOutputStream : public wxOutputStream +class wxProcessFileInputStream : public wxFileInputStream { public: - wxProcessFileOutputStream(int fd) { m_fd = fd; } - ~wxProcessFileOutputStream() { close(m_fd); } - -protected: - size_t OnSysWrite(const void *buffer, size_t bufsize); + wxProcessFileInputStream(int fd) : wxFileInputStream(fd) { } -protected: - int m_fd; + // return TRUE if we have anything to read, don't block + bool IsAvailable() const; }; -bool wxProcessFileInputStream::Eof() const +bool wxProcessFileInputStream::IsAvailable() const { if ( m_lasterror == wxSTREAM_EOF ) return TRUE; @@ -387,10 +372,12 @@ bool wxProcessFileInputStream::Eof() const tv.tv_sec = 0; tv.tv_usec = 0; + const int fd = m_file->fd(); + fd_set readfds; FD_ZERO(&readfds); - FD_SET(m_fd, &readfds); - switch ( select(m_fd + 1, &readfds, NULL, NULL, &tv) ) + FD_SET(fd, &readfds); + switch ( select(fd + 1, &readfds, NULL, NULL, &tv) ) { case -1: wxLogSysError(_("Impossible to get child process input")); @@ -404,49 +391,13 @@ bool wxProcessFileInputStream::Eof() const // still fall through case 1: - // input available: check if there is any - return wxInputStream::Eof(); - } -} - -size_t wxProcessFileInputStream::OnSysRead(void *buffer, size_t bufsize) -{ - int ret = read(m_fd, buffer, bufsize); - if ( ret == 0 ) - { - m_lasterror = wxSTREAM_EOF; - } - else if ( ret == -1 ) - { - m_lasterror = wxSTREAM_READ_ERROR; - ret = 0; - } - else - { - m_lasterror = wxSTREAM_NOERROR; - } - - return ret; -} - -size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize) -{ - int ret = write(m_fd, buffer, bufsize); - if ( ret == -1 ) - { - m_lasterror = wxSTREAM_WRITE_ERROR; - ret = 0; - } - else - { - m_lasterror = wxSTREAM_NOERROR; + // input available + return TRUE; } - - return ret; } // ---------------------------------------------------------------------------- -// wxStreamTempBuffer +// wxStreamTempInputBuffer // ---------------------------------------------------------------------------- /* @@ -471,7 +422,7 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize) have a classical deadlock. Here is the fix: we now read the output as soon as it appears into a temp - buffer (wxStreamTempBuffer object) and later just stuff it back into the + buffer (wxStreamTempInputBuffer object) and later just stuff it back into the stream when the process terminates. See supporting code in wxExecute() itself as well. @@ -480,23 +431,23 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize) needed! */ -class wxStreamTempBuffer +class wxStreamTempInputBuffer { public: - wxStreamTempBuffer(); + wxStreamTempInputBuffer(); // call to associate a stream with this buffer, otherwise nothing happens // at all - void Init(wxInputStream *stream); + void Init(wxProcessFileInputStream *stream); // check for input on our stream and cache it in our buffer if any void Update(); - ~wxStreamTempBuffer(); + ~wxStreamTempInputBuffer(); private: // the stream we're buffering, if NULL we don't do anything at all - wxInputStream *m_stream; + wxProcessFileInputStream *m_stream; // the buffer of size m_size (NULL if m_size == 0) void *m_buffer; @@ -505,21 +456,21 @@ private: size_t m_size; }; -wxStreamTempBuffer::wxStreamTempBuffer() +wxStreamTempInputBuffer::wxStreamTempInputBuffer() { m_stream = NULL; m_buffer = NULL; m_size = 0; } -void wxStreamTempBuffer::Init(wxInputStream *stream) +void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream) { m_stream = stream; } -void wxStreamTempBuffer::Update() +void wxStreamTempInputBuffer::Update() { - if ( m_stream && !m_stream->Eof() ) + if ( m_stream && m_stream->IsAvailable() ) { // realloc in blocks of 4Kb: this is the default (and minimal) buffer // size of the Unix pipes so it should be the optimal step @@ -540,7 +491,7 @@ void wxStreamTempBuffer::Update() } } -wxStreamTempBuffer::~wxStreamTempBuffer() +wxStreamTempInputBuffer::~wxStreamTempInputBuffer() { if ( m_buffer ) { @@ -552,7 +503,7 @@ wxStreamTempBuffer::~wxStreamTempBuffer() #endif // wxUSE_STREAMS // ---------------------------------------------------------------------------- -// wxPipe: this encpasulates pipe() system call +// wxPipe: this encapsulates pipe() system call // ---------------------------------------------------------------------------- class wxPipe @@ -715,12 +666,6 @@ long wxExecute(wxChar **argv, } else if ( pid == 0 ) // we're in child { -#if wxUSE_GUI - // reading side can be safely closed but we should keep the write one - // opened - pipeEndProcDetect.Detach(wxPipe::Write); -#endif // wxUSE_GUI - // These lines close the open file descriptors to to avoid any // input/output which might block the process or irritate the user. If // one wants proper IO for the subprocess, the right thing to do is to @@ -745,18 +690,25 @@ long wxExecute(wxChar **argv, if ( fd != STDERR_FILENO ) close(fd); } + } #ifndef __VMS - if ( flags & wxEXEC_MAKE_GROUP_LEADER ) - { - // Set process group to child process' pid. Then killing -pid - // of the parent will kill the process and all of its children. - setsid(); - } -#endif // !__VMS + if ( flags & wxEXEC_MAKE_GROUP_LEADER ) + { + // Set process group to child process' pid. Then killing -pid + // of the parent will kill the process and all of its children. + setsid(); } +#endif // !__VMS - // redirect stdio, stdout and stderr +#if wxUSE_GUI + // reading side can be safely closed but we should keep the write one + // opened + pipeEndProcDetect.Detach(wxPipe::Write); + pipeEndProcDetect.Close(); +#endif // wxUSE_GUI + + // redirect stdin, stdout and stderr if ( pipeIn.IsOk() ) { if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 || @@ -790,27 +742,30 @@ long wxExecute(wxChar **argv, { ARGS_CLEANUP; - // pipe initialization: construction of the wxStreams + // prepare for IO redirection + #if wxUSE_STREAMS - wxStreamTempBuffer bufIn, bufErr; + // the input buffer bufOut is connected to stdout, this is why it is + // called bufOut and not bufIn + wxStreamTempInputBuffer bufOut, + bufErr; #endif // wxUSE_STREAMS if ( process && process->IsRedirected() ) { #if wxUSE_STREAMS - // in/out for subprocess correspond to our out/in - wxOutputStream *outStream = - new wxProcessFileOutputStream(pipeIn.Detach(wxPipe::Write)); + wxOutputStream *inStream = + new wxFileOutputStream(pipeIn.Detach(wxPipe::Write)); - wxInputStream *inStream = + wxProcessFileInputStream *outStream = new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read)); - wxInputStream *errStream = + wxProcessFileInputStream *errStream = new wxProcessFileInputStream(pipeErr.Detach(wxPipe::Read)); - process->SetPipeStreams(inStream, outStream, errStream); + process->SetPipeStreams(outStream, inStream, errStream); - bufIn.Init(inStream); + bufOut.Init(outStream); bufErr.Init(errStream); #endif // wxUSE_STREAMS } @@ -850,7 +805,7 @@ long wxExecute(wxChar **argv, while ( data->pid != 0 ) { #if wxUSE_STREAMS - bufIn.Update(); + bufOut.Update(); bufErr.Update(); #endif // wxUSE_STREAMS @@ -889,6 +844,8 @@ long wxExecute(wxChar **argv, return exitcode; #endif // wxUSE_GUI } + + return ERROR_RETURN_CODE; } #undef ERROR_RETURN_CODE