X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/82baa5e4f1992b701e183544c935bcb424503f5b..503602dfe7fd468159d8d563657ad10c0bf6601f:/src/msw/utilsexc.cpp diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 43abd701ea..fbeb00691f 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -124,7 +124,7 @@ public: DWORD dwProcessId; // pid of the process wxProcess *handler; DWORD dwExitCode; // the exit code of the process - bool state; // set to FALSE when the process finishes + bool state; // set to false when the process finishes }; class wxExecuteModule : public wxModule @@ -160,10 +160,10 @@ public: wxPipeInputStream(HANDLE hInput); virtual ~wxPipeInputStream(); - // returns TRUE if the pipe is still opened + // returns true if the pipe is still opened bool IsOpened() const { return m_hInput != INVALID_HANDLE_VALUE; } - // returns TRUE if there is any data to be read from the pipe + // returns true if there is any data to be read from the pipe virtual bool CanRead() const; protected: @@ -179,7 +179,8 @@ class wxPipeOutputStream: public wxOutputStream { public: wxPipeOutputStream(HANDLE hOutput); - virtual ~wxPipeOutputStream(); + virtual ~wxPipeOutputStream() { Close(); } + bool Close(); protected: size_t OnSysWrite(const void *buffer, size_t len); @@ -211,7 +212,7 @@ public: // default ctor doesn't do anything wxPipe() { m_handles[Read] = m_handles[Write] = INVALID_HANDLE_VALUE; } - // create the pipe, return TRUE if ok, FALSE on error + // create the pipe, return true if ok, false on error bool Create() { // default secutiry attributes @@ -225,13 +226,13 @@ public: { wxLogSysError(_("Failed to create an anonymous pipe")); - return FALSE; + return false; } - return TRUE; + return true; } - // return TRUE if we were created successfully + // return true if we were created successfully bool IsOk() const { return m_handles[Read] != INVALID_HANDLE_VALUE; } // return the descriptor for one of the pipe ends @@ -362,7 +363,7 @@ wxPipeInputStream::~wxPipeInputStream() bool wxPipeInputStream::CanRead() const { if ( !IsOpened() ) - return FALSE; + return false; DWORD nAvailable; @@ -427,26 +428,54 @@ size_t wxPipeInputStream::OnSysRead(void *buffer, size_t len) wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput) { m_hOutput = hOutput; + + // unblock the pipe to prevent deadlocks when we're writing to the pipe + // from which the child process can't read because it is writing in its own + // end of it + DWORD mode = PIPE_READMODE_BYTE | PIPE_NOWAIT; + if ( !::SetNamedPipeHandleState + ( + m_hOutput, + &mode, + NULL, // collection count (we don't set it) + NULL // timeout (we don't set it neither) + ) ) + { + wxLogLastError(_T("SetNamedPipeHandleState(PIPE_NOWAIT)")); + } } -wxPipeOutputStream::~wxPipeOutputStream() +bool wxPipeOutputStream::Close() { - ::CloseHandle(m_hOutput); + return ::CloseHandle(m_hOutput) != 0; } + size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t len) { - DWORD bytesWritten; - m_lasterror = wxSTREAM_NO_ERROR; - if ( !::WriteFile(m_hOutput, buffer, len, &bytesWritten, NULL) ) + + DWORD totalWritten = 0; + while ( len > 0 ) { - m_lasterror = ::GetLastError() == ERROR_BROKEN_PIPE - ? wxSTREAM_EOF - : wxSTREAM_WRITE_ERROR; + DWORD chunkWritten; + if ( !::WriteFile(m_hOutput, buffer, len, &chunkWritten, NULL) ) + { + m_lasterror = ::GetLastError() == ERROR_BROKEN_PIPE + ? wxSTREAM_EOF + : wxSTREAM_WRITE_ERROR; + break; + } + + if ( !chunkWritten ) + break; + + buffer = (char *)buffer + chunkWritten; + totalWritten += chunkWritten; + len -= chunkWritten; } - return bytesWritten; + return totalWritten; } #endif // wxUSE_STREAMS @@ -470,7 +499,7 @@ static bool wxExecuteDDE(const wxString& ddeServer, ddeTopic); if ( !conn ) { - ok = FALSE; + ok = false; } else // connected to DDE server { @@ -502,7 +531,7 @@ static bool wxExecuteDDE(const wxString& ddeServer, long wxExecute(const wxString& cmd, int flags, wxProcess *handler) { - wxCHECK_MSG( !!cmd, 0, wxT("empty command in wxExecute") ); + wxCHECK_MSG( !cmd.empty(), 0, wxT("empty command in wxExecute") ); #if wxUSE_THREADS // for many reasons, the code below breaks down if it's called from another @@ -835,7 +864,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) case WAIT_TIMEOUT: wxLogDebug(_T("Timeout too small in WaitForInputIdle")); - ok = FALSE; + ok = false; break; case 0: @@ -862,8 +891,12 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; wxCHECK_MSG( traits, -1, _T("no wxAppTraits in wxExecute()?") ); - // disable all app windows while waiting for the child process to finish - void *cookie = traits->BeforeChildWaitLoop(); + void *cookie = NULL; + if ( !(flags & wxEXEC_NODISABLE) ) + { + // disable all app windows while waiting for the child process to finish + cookie = traits->BeforeChildWaitLoop(); + } // wait until the child process terminates while ( data->state ) @@ -881,7 +914,11 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler) traits->AlwaysYield(); } - traits->AfterChildWaitLoop(cookie); + if ( !(flags & wxEXEC_NODISABLE) ) + { + // reenable disabled windows back + traits->AfterChildWaitLoop(cookie); + } DWORD dwExitCode = data->dwExitCode; delete data;