Use SetHandleInformation() to make handle non-inheritable in wxMSW.

Simplify the code in wxExecute() by using SetHandleInformation() to make the
handle non-inheritable instead of duplicating it to achieve the same goal (the
old code worked under Windows 9x too, unlike the new one, but we don't care
about them any more).

See #16898.
This commit is contained in:
Richard Broker
2015-03-12 13:28:18 +01:00
committed by Vadim Zeitlin
parent 96a8240e87
commit a934346614

View File

@@ -694,9 +694,6 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
#if wxUSE_STREAMS && !defined(__WXWINCE__) #if wxUSE_STREAMS && !defined(__WXWINCE__)
wxPipe pipeIn, pipeOut, pipeErr; wxPipe pipeIn, pipeOut, pipeErr;
// we'll save here the copy of pipeIn[Write]
HANDLE hpipeStdinWrite = INVALID_HANDLE_VALUE;
// open the pipes to which child process IO will be redirected if needed // open the pipes to which child process IO will be redirected if needed
if ( handler && handler->IsRedirected() ) if ( handler && handler->IsRedirected() )
{ {
@@ -728,27 +725,16 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
si.hStdOutput = pipeOut[wxPipe::Write]; si.hStdOutput = pipeOut[wxPipe::Write];
si.hStdError = pipeErr[wxPipe::Write]; si.hStdError = pipeErr[wxPipe::Write];
// we must duplicate the handle to the write side of stdin pipe to make // We must set the handle to the side of the pipes that we won't use in
// it non inheritable: indeed, we must close the writing end of pipeIn // the child to be non-inheritable. We must do this before launching
// before launching the child process as otherwise this handle will be // the child process as otherwise these handles will be inherited by
// inherited by the child which will never close it and so the pipe // the child which will never close them and so the pipe will not
// will never be closed and the child will be left stuck in ReadFile() // return ERROR_BROKEN_PIPE if the parent or child exits unexpectedly
HANDLE pipeInWrite = pipeIn.Detach(wxPipe::Write); // causing the remaining process to potentially become deadlocked in
if ( !::DuplicateHandle // ReadFile().
( if ( !::SetHandleInformation(pipeIn[wxPipe::Write],
::GetCurrentProcess(), HANDLE_FLAG_INHERIT, 0) )
pipeInWrite, wxLogLastError(wxT("SetHandleInformation(pipeIn)"));
::GetCurrentProcess(),
&hpipeStdinWrite,
0, // desired access: unused here
FALSE, // not inherited
DUPLICATE_SAME_ACCESS // same access as for src handle
) )
{
wxLogLastError(wxT("DuplicateHandle"));
}
::CloseHandle(pipeInWrite);
} }
#endif // wxUSE_STREAMS #endif // wxUSE_STREAMS
@@ -889,6 +875,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
// close the other handles too // close the other handles too
if ( redirect ) if ( redirect )
{ {
::CloseHandle(pipeIn.Detach(wxPipe::Write));
::CloseHandle(pipeOut.Detach(wxPipe::Read)); ::CloseHandle(pipeOut.Detach(wxPipe::Read));
::CloseHandle(pipeErr.Detach(wxPipe::Read)); ::CloseHandle(pipeErr.Detach(wxPipe::Read));
} }
@@ -913,7 +900,7 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
wxPipeInputStream * wxPipeInputStream *
errStream = new wxPipeInputStream(pipeErr.Detach(wxPipe::Read)); errStream = new wxPipeInputStream(pipeErr.Detach(wxPipe::Read));
wxPipeOutputStream * wxPipeOutputStream *
inStream = new wxPipeOutputStream(hpipeStdinWrite); inStream = new wxPipeOutputStream(pipeIn.Detach(wxPipe::Write));
handler->SetPipeStreams(outStream, inStream, errStream); handler->SetPipeStreams(outStream, inStream, errStream);