Rework fix in r201744. You really DO need to waitpid twice to get the

process fully reaped.  The race & bad behavior was because we were letting
the reaping thread in LLDB to also set the Process exit status, so debugserver
would sometimes be shut down before it got a chance to report the exit status, 
and then we got confused.

<rdar://problem/16555850>

llvm-svn: 211636
This commit is contained in:
Jim Ingham 2014-06-24 21:51:42 +00:00
parent 5d1b9c7386
commit 6008924508
5 changed files with 13 additions and 11 deletions

View File

@ -824,9 +824,6 @@ public:
bool
MonitorProcess () const
{
if (GetFlags().Test(lldb::eLaunchFlagsDontMonitorProcess))
return true;
if (m_monitor_callback && ProcessIDIsValid())
{
Host::StartMonitoringChildProcess (m_monitor_callback,

View File

@ -47,8 +47,8 @@ namespace lldb {
eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host
eLaunchFlagLaunchInShell= (1u << 6), ///< Launch the process inside a shell to get shell expansion
eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7), ///< Launch the process in a separate process group
eLaunchFlagsDontMonitorProcess = (1u << 8) ///< If you are going to hand the process off (e.g. to debugserver)
///< set this flag so lldb & the handee don't race to reap it.
eLaunchFlagsDontSetExitStatus = (1u << 8) ///< If you are going to hand the process off (e.g. to debugserver)
///< set this flag so lldb & the handee don't race to set its exit status.
} LaunchFlags;
//----------------------------------------------------------------------

View File

@ -1667,7 +1667,12 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
if (!launch_info.MonitorProcess())
{
const bool monitor_signals = false;
StartMonitoringChildProcess (Process::SetProcessExitStatus,
Host::MonitorChildProcessCallback callback = nullptr;
if (!launch_info.GetFlags().Test(lldb::eLaunchFlagsDontSetExitStatus))
callback = Process::SetProcessExitStatus;
StartMonitoringChildProcess (callback,
NULL,
pid,
monitor_signals);

View File

@ -785,10 +785,10 @@ PlatformDarwin::DebugProcess (ProcessLaunchInfo &launch_info,
if (IsHost())
{
// We are going to hand this process off to debugserver which will monitor the process itself.
// So don't also monitor it from lldb or we set up a race between debugserver & us for who will find out
// about the debugged process's death.
launch_info.GetFlags().Set(eLaunchFlagsDontMonitorProcess);
// We are going to hand this process off to debugserver which will be in charge of setting the exit status.
// We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
// race between debugserver & us for who will find out about the debugged process's death.
launch_info.GetFlags().Set(eLaunchFlagsDontSetExitStatus);
process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error);
}
else

View File

@ -239,7 +239,7 @@ spawn_kqueue_thread (pid_t pid)
struct kevent reg_event;
EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXIT_DETAIL, 0, NULL);
EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL);
// Register the event:
int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
if (result != 0)