Debugger: Fix #11411.
CliContext/CommandLineUserInterface:
- Process the debug report event asynchronously. The missing lock that
was fixed in commit 5ac34e5a78
highlighted
a problem in how the CLI was handling the case where it was intended to
exit immediately after saving a report, since it issued the quit request
directly from the report event handler. This resulted in locking issues,
as the team debugger would then attempt to tear itself down, during which
it needs to acquire the team lock. However, that was already being held
by the thread in which the CLI was initiating the quit, resulting in a
deadlock.
This commit is contained in:
parent
9a6331459f
commit
8b9099b1b2
|
@ -97,6 +97,7 @@ CliContext::CliContext()
|
|||
fInputLoopWaitingForEvents(0),
|
||||
fEventsOccurred(0),
|
||||
fInputLoopWaiting(false),
|
||||
fInteractive(true),
|
||||
fTerminating(false),
|
||||
fCurrentThread(NULL),
|
||||
fCurrentStackTrace(NULL),
|
||||
|
@ -207,6 +208,13 @@ CliContext::Terminating()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
CliContext::SetInteractive(bool interactive)
|
||||
{
|
||||
fInteractive = interactive;
|
||||
}
|
||||
|
||||
|
||||
thread_id
|
||||
CliContext::CurrentThreadID() const
|
||||
{
|
||||
|
@ -444,6 +452,13 @@ CliContext::ProcessPendingEvents()
|
|||
fExpressionValue->AcquireReference();
|
||||
}
|
||||
break;
|
||||
case EVENT_DEBUG_REPORT_CHANGED:
|
||||
if (!IsInteractive()) {
|
||||
Terminating();
|
||||
QuitSession(true);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -503,6 +518,17 @@ CliContext::ExpressionEvaluated(const Team::ExpressionEvaluationEvent& event)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
CliContext::DebugReportChanged(const Team::DebugReportEvent& event)
|
||||
{
|
||||
printf("Successfully saved debug report to %s\n",
|
||||
event.GetReportPath());
|
||||
|
||||
_QueueEvent(new(std::nothrow) Event(EVENT_DEBUG_REPORT_CHANGED));
|
||||
_SignalInputLoop(EVENT_DEBUG_REPORT_CHANGED);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CliContext::MemoryBlockRetrieved(TeamMemoryBlock* block)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,8 @@ public:
|
|||
EVENT_THREAD_STACK_TRACE_CHANGED = 0x20,
|
||||
EVENT_VALUE_NODE_CHANGED = 0x40,
|
||||
EVENT_TEAM_MEMORY_BLOCK_RETRIEVED = 0x80,
|
||||
EVENT_EXPRESSION_EVALUATED = 0x100
|
||||
EVENT_EXPRESSION_EVALUATED = 0x100,
|
||||
EVENT_DEBUG_REPORT_CHANGED = 0x200
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -54,6 +55,9 @@ public:
|
|||
|
||||
bool IsTerminating() const { return fTerminating; }
|
||||
|
||||
bool IsInteractive() const { return fInteractive; }
|
||||
void SetInteractive(bool interactive);
|
||||
|
||||
// service methods for the input loop thread follow
|
||||
|
||||
Team* GetTeam() const { return fTeam; }
|
||||
|
@ -110,6 +114,9 @@ private:
|
|||
const Team::ExpressionEvaluationEvent&
|
||||
event);
|
||||
|
||||
virtual void DebugReportChanged(
|
||||
const Team::DebugReportEvent& event);
|
||||
|
||||
// TeamMemoryBlock::Listener
|
||||
virtual void MemoryBlockRetrieved(TeamMemoryBlock* block);
|
||||
|
||||
|
@ -141,6 +148,7 @@ private:
|
|||
uint32 fInputLoopWaitingForEvents;
|
||||
uint32 fEventsOccurred;
|
||||
bool fInputLoopWaiting;
|
||||
bool fInteractive;
|
||||
volatile bool fTerminating;
|
||||
|
||||
Thread* fCurrentThread;
|
||||
|
|
|
@ -128,6 +128,8 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener)
|
|||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fContext.SetInteractive(!fSaveReport);
|
||||
|
||||
error = _RegisterCommands();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
@ -229,11 +231,7 @@ CommandLineUserInterface::Run()
|
|||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
if (!fSaveReport) {
|
||||
_InputLoop();
|
||||
// Release the Show() semaphore to signal Terminate().
|
||||
release_sem(fShowSemaphore);
|
||||
} else {
|
||||
if (fSaveReport) {
|
||||
ArgumentVector args;
|
||||
char buffer[256];
|
||||
const char* parseErrorLocation;
|
||||
|
@ -245,6 +243,10 @@ CommandLineUserInterface::Run()
|
|||
} else
|
||||
_SubmitSaveReport();
|
||||
}
|
||||
|
||||
_InputLoop();
|
||||
// Release the Show() semaphore to signal Terminate().
|
||||
release_sem(fShowSemaphore);
|
||||
}
|
||||
|
||||
|
||||
|
@ -266,21 +268,6 @@ CommandLineUserInterface::ThreadStateChanged(const Team::ThreadEvent& event)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
CommandLineUserInterface::DebugReportChanged(
|
||||
const Team::DebugReportEvent& event)
|
||||
{
|
||||
printf("Successfully saved debug report to %s\n",
|
||||
event.GetReportPath());
|
||||
|
||||
if (fSaveReport) {
|
||||
fContext.QuitSession(true);
|
||||
// Release the Show() semaphore to signal Terminate().
|
||||
release_sem(fShowSemaphore);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
CommandLineUserInterface::_InputLoopEntry(void* data)
|
||||
{
|
||||
|
|
|
@ -55,8 +55,6 @@ public:
|
|||
// Team::Listener
|
||||
virtual void ThreadStateChanged(
|
||||
const Team::ThreadEvent& event);
|
||||
virtual void DebugReportChanged(
|
||||
const Team::DebugReportEvent& event);
|
||||
|
||||
private:
|
||||
struct CommandEntry;
|
||||
|
|
Loading…
Reference in New Issue