Fix race condition in Unix wxExecute() if child exited too quickly.

Check if the child has already finished before starting waiting for it.

Closes #16661.
This commit is contained in:
Kevin B. McCarty
2015-05-09 19:28:04 +02:00
committed by Vadim Zeitlin
parent 1ad4596e8c
commit 1298f5970b
2 changed files with 25 additions and 7 deletions

View File

@@ -67,6 +67,7 @@ All:
Unix: Unix:
- Fix bug in wxExecute() if child exited too quickly (Kevin B. McCarty).
- Add --disable-sys-libs configure option. - Add --disable-sys-libs configure option.
All (GUI): All (GUI):

View File

@@ -761,8 +761,6 @@ long wxExecute(char **argv, int flags, wxProcess *process,
} }
else // we're in parent else // we're in parent
{ {
execData.OnStart(pid);
// prepare for IO redirection // prepare for IO redirection
#if HAS_PIPE_STREAMS #if HAS_PIPE_STREAMS
@@ -814,17 +812,24 @@ long wxExecute(char **argv, int flags, wxProcess *process,
pipeErr.Close(); pipeErr.Close();
} }
// For the asynchronous case we don't have to do anything else, just
// let the process run.
if ( !(flags & wxEXEC_SYNC) ) if ( !(flags & wxEXEC_SYNC) )
{ {
// Ensure that the housekeeping data is kept alive, it will be // Ensure that the housekeeping data is kept alive, it will be
// destroyed only when the child terminates. // destroyed only when the child terminates.
execDataPtr.release(); execDataPtr.release();
return execData.pid;
} }
// Put the housekeeping data into the child process lookup table.
// Note that when running asynchronously, if the child has already
// finished this call will delete the execData and call any
// wxProcess's OnTerminate() handler immediately.
execData.OnStart(pid);
// For the asynchronous case we don't have to do anything else, just
// let the process run (if not already finished).
if ( !(flags & wxEXEC_SYNC) )
return pid;
// If we don't need to dispatch any events, things are relatively // If we don't need to dispatch any events, things are relatively
// simple and we don't need to delegate to wxAppTraits. // simple and we don't need to delegate to wxAppTraits.
@@ -1608,9 +1613,21 @@ void wxExecuteData::OnStart(int pid_)
if ( process ) if ( process )
process->SetPid(pid); process->SetPid(pid);
// Finally, add this object itself to the list of child processes so that // Add this object itself to the list of child processes so that
// we can check for its termination the next time we get SIGCHLD. // we can check for its termination the next time we get SIGCHLD.
ms_childProcesses[pid] = this; ms_childProcesses[pid] = this;
// However, if the child exited before we finished setting up above,
// we may have already missed its SIGCHLD. So we also do an explicit
// check here before returning.
int exitcode;
if ( CheckForChildExit(pid, &exitcode) )
{
// Handle its termination if it did.
// This call will implicitly remove it from ms_childProcesses
// and, if running asynchronously, it will delete itself.
OnExit(exitcode);
}
} }
void wxExecuteData::OnExit(int exitcode_) void wxExecuteData::OnExit(int exitcode_)