lldb can deadlock when launched with an non-existing executable:
% lldb /bin/nonono
(lldb) target create "/bin/nonono"
error: unable to find executable for '/usr/bin/nonono'
<deadlock>
The problem was the initial commands 'target create "/bin/nonono"' were put into a pipe and the command interpreter was being run with:
void
CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
bool spawn_thread,
CommandInterpreterRunOptions &options)
{
// Always re-create the command intepreter when we run it in case
// any file handles have changed.
bool force_create = true;
m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
m_stopped_for_crash = false;
if (auto_handle_events)
m_debugger.StartEventHandlerThread();
if (spawn_thread)
{
m_debugger.StartIOHandlerThread();
}
else
{
m_debugger.ExecuteIOHanders();
if (auto_handle_events)
m_debugger.StopEventHandlerThread();
}
}
If "auto_handle_events" was set to true and "spawn_thread" was false, we would execute:
m_debugger.StartEventHandlerThread();
m_debugger.ExecuteIOHanders();
m_debugger.StopEventHandlerThread();
The problem was there was no synchonization in Debugger::StartEventHandlerThread() to ensure the event handler was listening to events and the the call to "m_debugger.StopEventHandlerThread()" would do:
void
Debugger::StopEventHandlerThread()
{
if (m_event_handler_thread.IsJoinable())
{
GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived);
m_event_handler_thread.Join(nullptr);
}
}
The problem was that the event thread might not be listening for the CommandInterpreter::eBroadcastBitQuitCommandReceived event yet.
The solution is to make sure the Debugger::DefaultEventHandler() is listening to events before we return from Debugger::StartEventHandlerThread(). Once we have this synchonization we remove the race condition.
This fixes radar:
<rdar://problem/
19041192>
llvm-svn: 223083