X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0c9c44019068229a5f69f6b77bffff4008c2e208..11a2ce5ad289cb21b35cc21131b46f75dd4af060:/src/unix/utilsunx.cpp?ds=sidebyside diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 1976a20601..53f09c4b84 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: utilsunx.cpp +// Name: unix/utilsunx.cpp // Purpose: generic Unix implementation of many wx functions // Author: Vadim Zeitlin // Id: $Id$ @@ -253,7 +253,11 @@ long wxExecute( const wxString& command, int flags, wxProcess *process ) argv[argc] = NULL; // do execute the command +#if wxUSE_UNICODE + long lRc = -1; +#else long lRc = wxExecute(argv, flags, process); +#endif // clean up argc = 0; @@ -350,22 +354,25 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) #if wxUSE_STREAMS // ---------------------------------------------------------------------------- -// wxProcessFileInputStream: stream for reading from a pipe +// wxPipeInputStream: stream for reading from a pipe // ---------------------------------------------------------------------------- -class wxProcessFileInputStream : public wxFileInputStream +class wxPipeInputStream : public wxFileInputStream { public: - wxProcessFileInputStream(int fd) : wxFileInputStream(fd) { } + wxPipeInputStream(int fd) : wxFileInputStream(fd) { } + + // return TRUE if the pipe is still opened + bool IsOpened() const { return !Eof(); } // return TRUE if we have anything to read, don't block bool IsAvailable() const; }; -bool wxProcessFileInputStream::IsAvailable() const +bool wxPipeInputStream::IsAvailable() const { if ( m_lasterror == wxSTREAM_EOF ) - return TRUE; + return FALSE; // check if there is any input available struct timeval tv; @@ -384,121 +391,23 @@ bool wxProcessFileInputStream::IsAvailable() const // fall through case 0: - return TRUE; + return FALSE; default: wxFAIL_MSG(_T("unexpected select() return value")); // still fall through case 1: - // input available - return TRUE; - } -} - -// ---------------------------------------------------------------------------- -// wxStreamTempInputBuffer -// ---------------------------------------------------------------------------- - -/* - Extract of a mail to wx-users to give the context of the problem we are - trying to solve here: - - MC> If I run the command: - MC> find . -name "*.h" -exec grep linux {} \; - MC> in the exec sample synchronously from the 'Capture command output' - MC> menu, wxExecute never returns. I have to xkill it. Has anyone - MC> else encountered this? - - Yes, I can reproduce it too. - - I even think I understand why it happens: before launching the external - command we set up a pipe with a valid file descriptor on the reading side - when the output is redirected. So the subprocess happily writes to it ... - until the pipe buffer (which is usually quite big on Unix, I think the - default is 4Kb) is full. Then the writing process stops and waits until we - read some data from the pipe to be able to continue writing to it but we - never do it because we wait until it terminates to start reading and so we - have a classical deadlock. - - Here is the fix: we now read the output as soon as it appears into a temp - buffer (wxStreamTempInputBuffer object) and later just stuff it back into the - stream when the process terminates. See supporting code in wxExecute() - itself as well. - - Note that this is horribly inefficient for large amounts of output (count - the number of times we copy the data around) and so a better API is badly - needed! -*/ - -class wxStreamTempInputBuffer -{ -public: - wxStreamTempInputBuffer(); - - // call to associate a stream with this buffer, otherwise nothing happens - // at all - void Init(wxProcessFileInputStream *stream); - - // check for input on our stream and cache it in our buffer if any - void Update(); - - ~wxStreamTempInputBuffer(); - -private: - // the stream we're buffering, if NULL we don't do anything at all - wxProcessFileInputStream *m_stream; - - // the buffer of size m_size (NULL if m_size == 0) - void *m_buffer; - - // the size of the buffer - size_t m_size; -}; - -wxStreamTempInputBuffer::wxStreamTempInputBuffer() -{ - m_stream = NULL; - m_buffer = NULL; - m_size = 0; -} - -void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream) -{ - m_stream = stream; -} - -void wxStreamTempInputBuffer::Update() -{ - 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 - static const size_t incSize = 4096; - - void *buf = realloc(m_buffer, m_size + incSize); - if ( !buf ) - { - // don't read any more, we don't have enough memory to do it - m_stream = NULL; - } - else // got memory for the buffer - { - m_buffer = buf; - m_stream->Read((char *)m_buffer + m_size, incSize); - m_size += m_stream->LastRead(); - } + // input available -- or maybe not, as select() returns 1 when a + // read() will complete without delay, but it could still not read + // anything + return !Eof(); } } -wxStreamTempInputBuffer::~wxStreamTempInputBuffer() -{ - if ( m_buffer ) - { - m_stream->Ungetch(m_buffer, m_size); - free(m_buffer); - } -} +// define this to let wxexec.cpp know that we know what we're doing +#define _WX_USED_BY_WXEXECUTE_ +#include "../common/execcmn.cpp" #endif // wxUSE_STREAMS @@ -583,6 +492,10 @@ private: // wxExecute: the real worker function // ---------------------------------------------------------------------------- +#ifdef __VMS + #pragma message disable codeunreachable +#endif + long wxExecute(wxChar **argv, int flags, wxProcess *process) @@ -650,12 +563,10 @@ long wxExecute(wxChar **argv, } // fork the process -#ifdef HAVE_VFORK - pid_t pid = vfork(); -#else + // + // NB: do *not* use vfork() here, it completely breaks this code for some + // reason under Solaris (and maybe others, although not under Linux) pid_t pid = fork(); -#endif - if ( pid == -1 ) // error? { wxLogSysError( _("Fork failed") ); @@ -692,7 +603,7 @@ long wxExecute(wxChar **argv, } } -#ifndef __VMS +#if !defined(__VMS) && !defined(__EMX__) if ( flags & wxEXEC_MAKE_GROUP_LEADER ) { // Set process group to child process' pid. Then killing -pid @@ -757,11 +668,11 @@ long wxExecute(wxChar **argv, wxOutputStream *inStream = new wxFileOutputStream(pipeIn.Detach(wxPipe::Write)); - wxProcessFileInputStream *outStream = - new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read)); + wxPipeInputStream *outStream = + new wxPipeInputStream(pipeOut.Detach(wxPipe::Read)); - wxProcessFileInputStream *errStream = - new wxProcessFileInputStream(pipeErr.Detach(wxPipe::Read)); + wxPipeInputStream *errStream = + new wxPipeInputStream(pipeErr.Detach(wxPipe::Read)); process->SetPipeStreams(outStream, inStream, errStream); @@ -844,8 +755,14 @@ long wxExecute(wxChar **argv, return exitcode; #endif // wxUSE_GUI } + + return ERROR_RETURN_CODE; } +#ifdef __VMS + #pragma message enable codeunreachable +#endif + #undef ERROR_RETURN_CODE #undef ARGS_CLEANUP @@ -856,13 +773,13 @@ long wxExecute(wxChar **argv, const wxChar* wxGetHomeDir( wxString *home ) { *home = wxGetUserHome( wxString() ); - wxString tmp; + wxString tmp; if ( home->IsEmpty() ) *home = wxT("/"); #ifdef __VMS - tmp = *home; - if ( tmp.Last() != wxT(']')) - if ( tmp.Last() != wxT('/')) *home << wxT('/'); + tmp = *home; + if ( tmp.Last() != wxT(']')) + if ( tmp.Last() != wxT('/')) *home << wxT('/'); #endif return home->c_str(); } @@ -1097,9 +1014,9 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) // the case to "char *" is needed for AIX 4.3 wxStatFs fs; - if ( statfs((char *)path.fn_str(), &fs) != 0 ) + if ( statfs((char *)(const char*)path.fn_str(), &fs) != 0 ) { - wxLogSysError("Failed to get file system statistics"); + wxLogSysError( wxT("Failed to get file system statistics") ); return FALSE; }