diff --git a/docs/changes.txt b/docs/changes.txt index 82f6506aeb..d125bb1f5d 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -410,6 +410,10 @@ All: - Added wxThread::OnKill() and OnDelete() callbacks. - Added wxFile::GetLastError() and ClearLastError() (ryazanov). +Unix: + +- Fix spurious errors when writing to child process pipe (ryazanov). + All (GUI): - Added wxRichMessageDialog (Rickard Westerlund, GSoC 2010 project). diff --git a/include/wx/unix/pipe.h b/include/wx/unix/pipe.h index 3581008a6e..e4799024ed 100644 --- a/include/wx/unix/pipe.h +++ b/include/wx/unix/pipe.h @@ -118,6 +118,20 @@ public: virtual bool CanRead() const; }; +// ---------------------------------------------------------------------------- +// wxPipeOutputStream: stream for writing to a pipe +// ---------------------------------------------------------------------------- + +class wxPipeOutputStream : public wxFileOutputStream +{ +public: + wxPipeOutputStream(int fd) : wxFileOutputStream(fd) { } + + // Override the base class version to ignore "pipe full" errors: this is + // not an error for this class. + size_t OnSysWrite(const void *buffer, size_t size); +}; + #endif // wxUSE_STREAMS && wxUSE_FILE #endif // _WX_UNIX_PIPE_H_ diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 282f439258..a96e20e639 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -337,6 +337,45 @@ bool wxPipeInputStream::CanRead() const } } +size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t size) +{ + // We need to suppress error logging here, because on writing to a pipe + // which is full, wxFile::Write reports a system error. However, this is + // not an extraordinary situation, and it should not be reported to the + // user (but if really needed, the program can recognize it by checking + // whether LastRead() == 0.) Other errors will be reported below. + size_t ret; + { + wxLogNull logNo; + ret = m_file->Write(buffer, size); + } + + switch ( m_file->GetLastError() ) + { + // pipe is full +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + // do not treat it as an error + m_file->ClearLastError(); + // fall through + + // no error + case 0: + break; + + // some real error + default: + wxLogSysError(_("Can't write to child process's stdin")); + m_lasterror = wxSTREAM_WRITE_ERROR; + } + + return ret; +} + #endif // HAS_PIPE_STREAMS // ---------------------------------------------------------------------------- @@ -662,10 +701,11 @@ long wxExecute(char **argv, int flags, wxProcess *process, // it might not be the best idea. wxLogSysError(_("Failed to set up non-blocking pipe, " "the program might hang.")); + wxLog::FlushActive(); } wxOutputStream *inStream = - new wxFileOutputStream(pipeIn.Detach(wxPipe::Write)); + new wxPipeOutputStream(pipeIn.Detach(wxPipe::Write)); const int fdOut = pipeOut.Detach(wxPipe::Read); wxPipeInputStream *outStream = new wxPipeInputStream(fdOut);