use wxFileInput/OutputStreams instead of reproducing their functionality in wxProcessFileInput/OutputStream
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16153 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
#include "wx/process.h"
|
#include "wx/process.h"
|
||||||
#include "wx/thread.h"
|
#include "wx/thread.h"
|
||||||
|
|
||||||
#include "wx/stream.h"
|
#include "wx/wfstream.h"
|
||||||
|
|
||||||
#ifdef HAVE_STATFS
|
#ifdef HAVE_STATFS
|
||||||
# ifdef __BSD__
|
# ifdef __BSD__
|
||||||
@@ -349,35 +349,20 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data)
|
|||||||
|
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
|
|
||||||
class wxProcessFileInputStream : public wxInputStream
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxProcessFileInputStream: stream for reading from a pipe
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxProcessFileInputStream : public wxFileInputStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxProcessFileInputStream(int fd) { m_fd = fd; }
|
wxProcessFileInputStream(int fd) : wxFileInputStream(fd) { }
|
||||||
~wxProcessFileInputStream() { close(m_fd); }
|
|
||||||
|
|
||||||
virtual bool Eof() const;
|
// return TRUE if we have anything to read, don't block
|
||||||
|
bool IsAvailable() const;
|
||||||
protected:
|
|
||||||
size_t OnSysRead(void *buffer, size_t bufsize);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int m_fd;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxProcessFileOutputStream : public wxOutputStream
|
bool wxProcessFileInputStream::IsAvailable() const
|
||||||
{
|
|
||||||
public:
|
|
||||||
wxProcessFileOutputStream(int fd) { m_fd = fd; }
|
|
||||||
~wxProcessFileOutputStream() { close(m_fd); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t OnSysWrite(const void *buffer, size_t bufsize);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int m_fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool wxProcessFileInputStream::Eof() const
|
|
||||||
{
|
{
|
||||||
if ( m_lasterror == wxSTREAM_EOF )
|
if ( m_lasterror == wxSTREAM_EOF )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -387,10 +372,12 @@ bool wxProcessFileInputStream::Eof() const
|
|||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
const int fd = m_file->fd();
|
||||||
|
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
FD_SET(m_fd, &readfds);
|
FD_SET(fd, &readfds);
|
||||||
switch ( select(m_fd + 1, &readfds, NULL, NULL, &tv) )
|
switch ( select(fd + 1, &readfds, NULL, NULL, &tv) )
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
wxLogSysError(_("Impossible to get child process input"));
|
wxLogSysError(_("Impossible to get child process input"));
|
||||||
@@ -404,49 +391,13 @@ bool wxProcessFileInputStream::Eof() const
|
|||||||
// still fall through
|
// still fall through
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// input available: check if there is any
|
// input available
|
||||||
return wxInputStream::Eof();
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxStreamTempBuffer
|
// wxStreamTempInputBuffer
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -471,7 +422,7 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
|
|||||||
have a classical deadlock.
|
have a classical deadlock.
|
||||||
|
|
||||||
Here is the fix: we now read the output as soon as it appears into a temp
|
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()
|
stream when the process terminates. See supporting code in wxExecute()
|
||||||
itself as well.
|
itself as well.
|
||||||
|
|
||||||
@@ -480,23 +431,23 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
|
|||||||
needed!
|
needed!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class wxStreamTempBuffer
|
class wxStreamTempInputBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxStreamTempBuffer();
|
wxStreamTempInputBuffer();
|
||||||
|
|
||||||
// call to associate a stream with this buffer, otherwise nothing happens
|
// call to associate a stream with this buffer, otherwise nothing happens
|
||||||
// at all
|
// at all
|
||||||
void Init(wxInputStream *stream);
|
void Init(wxProcessFileInputStream *stream);
|
||||||
|
|
||||||
// check for input on our stream and cache it in our buffer if any
|
// check for input on our stream and cache it in our buffer if any
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
~wxStreamTempBuffer();
|
~wxStreamTempInputBuffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// the stream we're buffering, if NULL we don't do anything at all
|
// 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)
|
// the buffer of size m_size (NULL if m_size == 0)
|
||||||
void *m_buffer;
|
void *m_buffer;
|
||||||
@@ -505,21 +456,21 @@ private:
|
|||||||
size_t m_size;
|
size_t m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxStreamTempBuffer::wxStreamTempBuffer()
|
wxStreamTempInputBuffer::wxStreamTempInputBuffer()
|
||||||
{
|
{
|
||||||
m_stream = NULL;
|
m_stream = NULL;
|
||||||
m_buffer = NULL;
|
m_buffer = NULL;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxStreamTempBuffer::Init(wxInputStream *stream)
|
void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream)
|
||||||
{
|
{
|
||||||
m_stream = 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
|
// realloc in blocks of 4Kb: this is the default (and minimal) buffer
|
||||||
// size of the Unix pipes so it should be the optimal step
|
// 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 )
|
if ( m_buffer )
|
||||||
{
|
{
|
||||||
@@ -552,7 +503,7 @@ wxStreamTempBuffer::~wxStreamTempBuffer()
|
|||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxPipe: this encpasulates pipe() system call
|
// wxPipe: this encapsulates pipe() system call
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class wxPipe
|
class wxPipe
|
||||||
@@ -756,7 +707,7 @@ long wxExecute(wxChar **argv,
|
|||||||
#endif // !__VMS
|
#endif // !__VMS
|
||||||
}
|
}
|
||||||
|
|
||||||
// redirect stdio, stdout and stderr
|
// redirect stdin, stdout and stderr
|
||||||
if ( pipeIn.IsOk() )
|
if ( pipeIn.IsOk() )
|
||||||
{
|
{
|
||||||
if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 ||
|
if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 ||
|
||||||
@@ -790,27 +741,30 @@ long wxExecute(wxChar **argv,
|
|||||||
{
|
{
|
||||||
ARGS_CLEANUP;
|
ARGS_CLEANUP;
|
||||||
|
|
||||||
// pipe initialization: construction of the wxStreams
|
// prepare for IO redirection
|
||||||
|
|
||||||
#if wxUSE_STREAMS
|
#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
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
if ( process && process->IsRedirected() )
|
if ( process && process->IsRedirected() )
|
||||||
{
|
{
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
// in/out for subprocess correspond to our out/in
|
wxOutputStream *inStream =
|
||||||
wxOutputStream *outStream =
|
new wxFileOutputStream(pipeIn.Detach(wxPipe::Write));
|
||||||
new wxProcessFileOutputStream(pipeIn.Detach(wxPipe::Write));
|
|
||||||
|
|
||||||
wxInputStream *inStream =
|
wxProcessFileInputStream *outStream =
|
||||||
new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read));
|
new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read));
|
||||||
|
|
||||||
wxInputStream *errStream =
|
wxProcessFileInputStream *errStream =
|
||||||
new wxProcessFileInputStream(pipeErr.Detach(wxPipe::Read));
|
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);
|
bufErr.Init(errStream);
|
||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
}
|
}
|
||||||
@@ -850,7 +804,7 @@ long wxExecute(wxChar **argv,
|
|||||||
while ( data->pid != 0 )
|
while ( data->pid != 0 )
|
||||||
{
|
{
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
bufIn.Update();
|
bufOut.Update();
|
||||||
bufErr.Update();
|
bufErr.Update();
|
||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user