Debugger: Make CliContext use BLooper for message passing

This commit replaces the custom implementation of message passing with
BLooper.

This commit does not fully transition the code to the BLooper paradigm.
WaitForEvent still exists, when, ideally, message passing should be
used to notify the waiting class that the results are ready.

Change-Id: Id223b9fc0ac1aa9a5a5aeb4af63da04f2cc7574b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6400
Reviewed-by: John Scipione <[email protected]>
Reviewed-by: Rene Gollent <[email protected]>
This commit is contained in:
Zardshard
2023-08-04 17:29:49 +00:00
committed by waddlesplash
parent 9b28ebf997
commit 45e0c33d4f
6 changed files with 225 additions and 256 deletions
@@ -29,7 +29,7 @@ static CliContext* sCurrentContext;
struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
Event(int type, Thread* thread = NULL, TeamMemoryBlock* block = NULL,
Event(int type, ::Thread* thread = NULL, TeamMemoryBlock* block = NULL,
ExpressionInfo* info = NULL, status_t expressionResult = B_OK,
ExpressionResult* expressionValue = NULL)
:
@@ -47,7 +47,7 @@ struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
return fType;
}
Thread* GetThread() const
::Thread* GetThread() const
{
return fThreadReference.Get();
}
@@ -75,7 +75,7 @@ struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
private:
int fType;
BReference<Thread> fThreadReference;
BReference< ::Thread> fThreadReference;
BReference<TeamMemoryBlock> fMemoryBlockReference;
BReference<ExpressionInfo> fExpressionInfo;
status_t fExpressionResult;
@@ -88,6 +88,7 @@ private:
CliContext::CliContext()
:
BLooper("CliContext"),
fLock("CliContext"),
fTeam(NULL),
fListener(NULL),
@@ -95,10 +96,8 @@ CliContext::CliContext()
fEditLine(NULL),
fHistory(NULL),
fPrompt(NULL),
fBlockingSemaphore(-1),
fInputLoopWaitingForEvents(0),
fEventsOccurred(0),
fInputLoopWaiting(false),
fWaitForEventSemaphore(-1),
fEventOccurred(0),
fTerminating(false),
fStoppedThread(NULL),
fCurrentThread(NULL),
@@ -118,14 +117,16 @@ CliContext::~CliContext()
Cleanup();
sCurrentContext = NULL;
if (fBlockingSemaphore >= 0)
delete_sem(fBlockingSemaphore);
if (fWaitForEventSemaphore >= 0)
delete_sem(fWaitForEventSemaphore);
}
status_t
CliContext::Init(Team* team, UserInterfaceListener* listener)
CliContext::Init(::Team* team, UserInterfaceListener* listener)
{
AutoLocker<BLocker> locker(fLock);
fTeam = team;
fListener = listener;
@@ -135,9 +136,9 @@ CliContext::Init(Team* team, UserInterfaceListener* listener)
if (error != B_OK)
return error;
fBlockingSemaphore = create_sem(0, "CliContext block");
if (fBlockingSemaphore < 0)
return fBlockingSemaphore;
fWaitForEventSemaphore = create_sem(0, "CliContext wait for event");
if (fWaitForEventSemaphore < 0)
return fWaitForEventSemaphore;
fEditLine = el_init("Debugger", stdin, stdout, stderr);
if (fEditLine == NULL)
@@ -171,11 +172,9 @@ CliContext::Init(Team* team, UserInterfaceListener* listener)
void
CliContext::Cleanup()
{
AutoLocker<BLocker> locker(fLock);
Terminating();
while (Event* event = fPendingEvents.RemoveHead())
delete event;
if (fEditLine != NULL) {
el_end(fEditLine);
fEditLine = NULL;
@@ -208,13 +207,16 @@ CliContext::Cleanup()
}
// TODO: Use the lifecycle methods of BLooper instead
void
CliContext::Terminating()
{
AutoLocker<BLocker> locker(fLock);
fTerminating = true;
_SignalInputLoop(EVENT_QUIT);
BMessage message(MSG_QUIT);
PostMessage(&message);
// TODO: Signal the input loop, should it be in PromptUser()!
}
@@ -223,12 +225,13 @@ CliContext::Terminating()
thread_id
CliContext::CurrentThreadID() const
{
AutoLocker<BLocker> locker(fLock);
return fCurrentThread != NULL ? fCurrentThread->ID() : -1;
}
void
CliContext::SetCurrentThread(Thread* thread)
CliContext::SetCurrentThread(::Thread* thread)
{
AutoLocker<BLocker> locker(fLock);
@@ -262,7 +265,8 @@ CliContext::SetCurrentThread(Thread* thread)
void
CliContext::PrintCurrentThread()
{
AutoLocker<Team> teamLocker(fTeam);
AutoLocker< ::Team> teamLocker(fTeam);
AutoLocker<BLocker> locker(fLock);
if (fCurrentThread != NULL) {
printf("current thread: %" B_PRId32 " \"%s\"\n", fCurrentThread->ID(),
@@ -294,11 +298,12 @@ status_t
CliContext::EvaluateExpression(const char* expression,
SourceLanguage* language, target_addr_t& address)
{
AutoLocker<BLocker> locker(fLock);
fExpressionInfo->SetTo(expression);
fListener->ExpressionEvaluationRequested(
language, fExpressionInfo);
WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
_WaitForEvent(MSG_EXPRESSION_EVALUATED);
if (fTerminating)
return B_INTERRUPTED;
@@ -329,9 +334,10 @@ CliContext::EvaluateExpression(const char* expression,
status_t
CliContext::GetMemoryBlock(target_addr_t address, TeamMemoryBlock*& block)
{
AutoLocker<BLocker> locker(fLock);
if (fCurrentBlock == NULL || !fCurrentBlock->Contains(address)) {
GetUserInterfaceListener()->InspectRequested(address, this);
WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
_WaitForEvent(MSG_TEAM_MEMORY_BLOCK_RETRIEVED);
if (fTerminating)
return B_INTERRUPTED;
}
@@ -351,8 +357,6 @@ CliContext::PromptUser(const char* prompt)
fPrompt = NULL;
ProcessPendingEvents();
return line;
}
@@ -368,14 +372,12 @@ CliContext::AddLineToInputHistory(const char* line)
void
CliContext::QuitSession(bool killTeam)
{
_PrepareToWaitForEvents(EVENT_QUIT);
fListener->UserInterfaceQuitRequested(
killTeam
? UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM
: UserInterfaceListener::QUIT_OPTION_ASK_RESUME_TEAM);
_WaitForEvents();
WaitForEvent(MSG_QUIT);
}
@@ -384,19 +386,10 @@ CliContext::WaitForThreadOrUser()
{
// TODO: Deal with SIGINT as well!
// if no thread has been stopped, wait till one is
while (fStoppedThread == NULL) {
_PrepareToWaitForEvents(
EVENT_USER_INTERRUPT | EVENT_THREAD_STATE_CHANGED);
uint32 events = _WaitForEvents();
AutoLocker<BLocker> locker(fLock);
ProcessPendingEvents();
// updates fStoppedThread if any thread has been stopped
if ((events & EVENT_QUIT) != 0) {
return;
}
}
while (fStoppedThread == NULL)
_WaitForEvent(MSG_THREAD_STATE_CHANGED);
if (fCurrentThread == NULL)
SetCurrentThread(fStoppedThread);
@@ -404,116 +397,138 @@ CliContext::WaitForThreadOrUser()
void
CliContext::WaitForEvents(int32 eventMask)
{
for (;;) {
_PrepareToWaitForEvents(eventMask | EVENT_USER_INTERRUPT);
uint32 events = fEventsOccurred;
if ((events & eventMask) == 0) {
events = _WaitForEvents();
}
if ((events & EVENT_QUIT) != 0 || (events & eventMask) != 0) {
_SignalInputLoop(eventMask);
ProcessPendingEvents();
return;
}
}
CliContext::WaitForEvent(uint32 event) {
AutoLocker<BLocker> locker(fLock);
_WaitForEvent(event);
}
void
CliContext::ProcessPendingEvents()
CliContext::MessageReceived(BMessage* message)
{
AutoLocker<Team> teamLocker(fTeam);
fLock.Lock();
for (;;) {
// get the next event
AutoLocker<BLocker> locker(fLock);
Event* event = fPendingEvents.RemoveHead();
locker.Unlock();
if (event == NULL)
int32 threadID;
message->FindInt32("thread", &threadID);
const char* threadName;
message->FindString("threadName", &threadName);
switch (message->what) {
case MSG_THREAD_ADDED:
printf("[new thread: %" B_PRId32 " \"%s\"]\n", threadID,
threadName);
break;
ObjectDeleter<Event> eventDeleter(event);
case MSG_THREAD_REMOVED:
printf("[thread terminated: %" B_PRId32 " \"%s\"]\n",
threadID, threadName);
break;
case MSG_THREAD_STATE_CHANGED:
{
AutoLocker< ::Team> locker(fTeam);
::Thread* thread = fTeam->ThreadByID(threadID);
// process the event
Thread* thread = event->GetThread();
switch (event->Type()) {
case EVENT_QUIT:
case EVENT_DEBUG_REPORT_CHANGED:
case EVENT_USER_INTERRUPT:
break;
case EVENT_THREAD_ADDED:
printf("[new thread: %" B_PRId32 " \"%s\"]\n", thread->ID(),
thread->Name());
break;
case EVENT_THREAD_REMOVED:
printf("[thread terminated: %" B_PRId32 " \"%s\"]\n",
thread->ID(), thread->Name());
break;
case EVENT_THREAD_STATE_CHANGED:
if (thread->State() == THREAD_STATE_STOPPED) {
printf("[thread stopped: %" B_PRId32 " \"%s\"]\n",
thread->ID(), thread->Name());
fStoppedThread.SetTo(thread);
} else {
fStoppedThread = NULL;
}
break;
case EVENT_THREAD_STACK_TRACE_CHANGED:
if (thread == fCurrentThread) {
fCurrentStackTrace = thread->GetStackTrace();
fCurrentStackTrace->AcquireReference();
SetCurrentStackFrameIndex(0);
}
break;
case EVENT_TEAM_MEMORY_BLOCK_RETRIEVED:
if (fCurrentBlock != NULL) {
fCurrentBlock->ReleaseReference();
fCurrentBlock = NULL;
}
fCurrentBlock = event->GetMemoryBlock();
break;
case EVENT_EXPRESSION_EVALUATED:
fExpressionResult = event->GetExpressionResult();
if (fExpressionValue != NULL) {
fExpressionValue->ReleaseReference();
fExpressionValue = NULL;
}
fExpressionValue = event->GetExpressionValue();
if (fExpressionValue != NULL)
fExpressionValue->AcquireReference();
break;
if (thread->State() == THREAD_STATE_STOPPED) {
printf("[thread stopped: %" B_PRId32 " \"%s\"]\n",
threadID, threadName);
fStoppedThread.SetTo(thread);
} else {
fStoppedThread = NULL;
}
break;
}
case MSG_THREAD_STACK_TRACE_CHANGED:
if (threadID == fCurrentThread->ID()) {
AutoLocker< ::Team> locker(fTeam);
::Thread* thread = fTeam->ThreadByID(threadID);
fCurrentStackTrace = thread->GetStackTrace();
fCurrentStackTrace->AcquireReference();
SetCurrentStackFrameIndex(0);
}
break;
case MSG_TEAM_MEMORY_BLOCK_RETRIEVED:
{
TeamMemoryBlock* block = NULL;
if (message->FindPointer("block",
reinterpret_cast<void **>(&block)) != B_OK) {
break;
}
if (fCurrentBlock != NULL) {
fCurrentBlock->ReleaseReference();
}
// reference acquired in MemoryBlockRetrieved
fCurrentBlock = block;
break;
}
case MSG_EXPRESSION_EVALUATED:
{
status_t result;
if (message->FindInt32("result", &result) != B_OK) {
break;
}
fExpressionResult = result;
ExpressionResult* value = NULL;
message->FindPointer("value", reinterpret_cast<void**>(&value));
if (fExpressionValue != NULL) {
fExpressionValue->ReleaseReference();
}
// reference acquired in ExpressionEvaluated
fExpressionValue = value;
break;
}
default:
BLooper::MessageReceived(message);
break;
}
fEventOccurred = message->what;
fLock.Unlock();
release_sem(fWaitForEventSemaphore);
// all of the code that was waiting on the semaphore runs
acquire_sem(fWaitForEventSemaphore);
fLock.Lock();
fEventOccurred = 0;
fLock.Unlock();
}
void
CliContext::ThreadAdded(const Team::ThreadEvent& threadEvent)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_THREAD_ADDED, threadEvent.GetThread()));
_SignalInputLoop(EVENT_THREAD_ADDED);
BMessage message(MSG_THREAD_ADDED);
message.AddInt32("thread", threadEvent.GetThread()->ID());
message.AddString("threadName", threadEvent.GetThread()->Name());
PostMessage(&message);
}
void
CliContext::ThreadRemoved(const Team::ThreadEvent& threadEvent)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_THREAD_REMOVED, threadEvent.GetThread()));
_SignalInputLoop(EVENT_THREAD_REMOVED);
BMessage message(MSG_THREAD_REMOVED);
message.AddInt32("thread", threadEvent.GetThread()->ID());
message.AddString("threadName", threadEvent.GetThread()->Name());
PostMessage(&message);
}
void
CliContext::ThreadStateChanged(const Team::ThreadEvent& threadEvent)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_THREAD_STATE_CHANGED, threadEvent.GetThread()));
_SignalInputLoop(EVENT_THREAD_STATE_CHANGED);
BMessage message(MSG_THREAD_STATE_CHANGED);
message.AddInt32("thread", threadEvent.GetThread()->ID());
message.AddString("threadName", threadEvent.GetThread()->Name());
PostMessage(&message);
}
@@ -523,10 +538,10 @@ CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent)
if (threadEvent.GetThread()->State() != THREAD_STATE_STOPPED)
return;
_QueueEvent(
new(std::nothrow) Event(EVENT_THREAD_STACK_TRACE_CHANGED,
threadEvent.GetThread()));
_SignalInputLoop(EVENT_THREAD_STACK_TRACE_CHANGED);
BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
message.AddInt32("thread", threadEvent.GetThread()->ID());
message.AddString("threadName", threadEvent.GetThread()->Name());
PostMessage(&message);
}
@@ -534,10 +549,15 @@ void
CliContext::ExpressionEvaluated(ExpressionInfo* info, status_t result,
ExpressionResult* value)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_EXPRESSION_EVALUATED,
NULL, NULL, info, result, value));
_SignalInputLoop(EVENT_EXPRESSION_EVALUATED);
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddInt32("result", result);
if (value != NULL) {
value->AcquireReference();
message.AddPointer("value", value);
}
PostMessage(&message);
}
@@ -551,9 +571,6 @@ CliContext::DebugReportChanged(const Team::DebugReportEvent& event)
fprintf(stderr, "Failed to write debug report: %s\n", strerror(
event.GetFinalStatus()));
}
_QueueEvent(new(std::nothrow) Event(EVENT_DEBUG_REPORT_CHANGED));
_SignalInputLoop(EVENT_DEBUG_REPORT_CHANGED);
}
@@ -562,19 +579,18 @@ CliContext::CoreFileChanged(const Team::CoreFileChangedEvent& event)
{
printf("Successfully saved core file to %s\n",
event.GetTargetPath());
_QueueEvent(new(std::nothrow) Event(EVENT_CORE_FILE_CHANGED));
_SignalInputLoop(EVENT_CORE_FILE_CHANGED);
}
void
CliContext::MemoryBlockRetrieved(TeamMemoryBlock* block)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_TEAM_MEMORY_BLOCK_RETRIEVED,
NULL, block));
_SignalInputLoop(EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
if (block != NULL)
block->AcquireReference();
BMessage message(MSG_TEAM_MEMORY_BLOCK_RETRIEVED);
message.AddPointer("block", block);
PostMessage(&message);
}
@@ -582,92 +598,32 @@ void
CliContext::ValueNodeChanged(ValueNodeChild* nodeChild, ValueNode* oldNode,
ValueNode* newNode)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
BMessage message(MSG_VALUE_NODE_CHANGED);
PostMessage(&message);
}
void
CliContext::ValueNodeChildrenCreated(ValueNode* node)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
BMessage message(MSG_VALUE_NODE_CHANGED);
PostMessage(&message);
}
void
CliContext::ValueNodeChildrenDeleted(ValueNode* node)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
BMessage message(MSG_VALUE_NODE_CHANGED);
PostMessage(&message);
}
void
CliContext::ValueNodeValueChanged(ValueNode* oldNode)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
}
void
CliContext::_QueueEvent(Event* event)
{
if (event == NULL) {
// no memory -- can't do anything about it
return;
}
AutoLocker<BLocker> locker(fLock);
fPendingEvents.Add(event);
}
void
CliContext::_PrepareToWaitForEvents(uint32 eventMask)
{
// Set the events we're going to wait for -- always wait for "quit".
AutoLocker<BLocker> locker(fLock);
fInputLoopWaitingForEvents = eventMask | EVENT_QUIT;
fEventsOccurred = fTerminating ? EVENT_QUIT : 0;
}
uint32
CliContext::_WaitForEvents()
{
AutoLocker<BLocker> locker(fLock);
if (fEventsOccurred == 0) {
sem_id blockingSemaphore = fBlockingSemaphore;
fInputLoopWaiting = true;
locker.Unlock();
while (acquire_sem(blockingSemaphore) == B_INTERRUPTED) {
}
locker.Lock();
}
uint32 events = fEventsOccurred;
fEventsOccurred = 0;
return events;
}
void
CliContext::_SignalInputLoop(uint32 events)
{
AutoLocker<BLocker> locker(fLock);
if ((fInputLoopWaitingForEvents & events) == 0)
return;
fEventsOccurred = fInputLoopWaitingForEvents & events;
fInputLoopWaitingForEvents = 0;
if (fInputLoopWaiting) {
fInputLoopWaiting = false;
release_sem(fBlockingSemaphore);
}
BMessage message(MSG_VALUE_NODE_CHANGED);
PostMessage(&message);
}
@@ -676,3 +632,19 @@ CliContext::_GetPrompt(EditLine* editLine)
{
return sCurrentContext != NULL ? sCurrentContext->fPrompt : NULL;
}
void
CliContext::_WaitForEvent(uint32 event) {
if (fTerminating)
return;
do {
fLock.Unlock();
while (acquire_sem(fWaitForEventSemaphore) == B_INTERRUPTED) {
}
fLock.Lock();
release_sem(fWaitForEventSemaphore);
} while (fEventOccurred != event && !fTerminating);
}
@@ -12,6 +12,7 @@
#include <histedit.h>
#include <Locker.h>
#include <Looper.h>
#include "ExpressionInfo.h"
#include "Team.h"
@@ -31,27 +32,28 @@ class ValueNodeManager;
class CliContext : private Team::Listener,
public TeamMemoryBlock::Listener,
public ExpressionInfo::Listener,
private ValueNodeContainer::Listener {
private ValueNodeContainer::Listener,
public BLooper {
public:
enum {
EVENT_QUIT = 0x01,
EVENT_USER_INTERRUPT = 0x02,
EVENT_THREAD_ADDED = 0x04,
EVENT_THREAD_REMOVED = 0x08,
EVENT_THREAD_STATE_CHANGED = 0x10,
EVENT_THREAD_STACK_TRACE_CHANGED = 0x20,
EVENT_VALUE_NODE_CHANGED = 0x40,
EVENT_TEAM_MEMORY_BLOCK_RETRIEVED = 0x80,
EVENT_EXPRESSION_EVALUATED = 0x100,
EVENT_DEBUG_REPORT_CHANGED = 0x200,
EVENT_CORE_FILE_CHANGED = 0x400
MSG_QUIT = 'quit',
MSG_USER_INTERRUPT = 'uint',
MSG_THREAD_ADDED = 'thad',
MSG_THREAD_REMOVED = 'thar',
MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
MSG_VALUE_NODE_CHANGED = 'vnch',
MSG_TEAM_MEMORY_BLOCK_RETRIEVED = 'tmbr',
MSG_EXPRESSION_EVALUATED = 'exev',
MSG_DEBUG_REPORT_CHANGED = 'drch',
MSG_CORE_FILE_CHANGED = 'cfch'
};
public:
CliContext();
~CliContext();
status_t Init(Team* team,
status_t Init(::Team* team,
UserInterfaceListener* listener);
void Cleanup();
@@ -59,9 +61,11 @@ public:
bool IsTerminating() const { return fTerminating; }
virtual void MessageReceived(BMessage* message);
// service methods for the input loop thread follow
Team* GetTeam() const { return fTeam; }
::Team* GetTeam() const { return fTeam; }
UserInterfaceListener* GetUserInterfaceListener() const
{ return fListener; }
ValueNodeManager* GetValueNodeManager() const
@@ -69,9 +73,9 @@ public:
StackTrace* GetStackTrace() const
{ return fCurrentStackTrace; }
Thread* CurrentThread() const { return fCurrentThread; }
::Thread* CurrentThread() const { return fCurrentThread; }
thread_id CurrentThreadID() const;
void SetCurrentThread(Thread* thread);
void SetCurrentThread(::Thread* thread);
void PrintCurrentThread();
int32 CurrentStackFrameIndex() const
@@ -90,8 +94,7 @@ public:
void QuitSession(bool killTeam);
void WaitForThreadOrUser();
void WaitForEvents(int32 eventMask);
void ProcessPendingEvents();
void WaitForEvent(uint32 event);
private:
struct Event;
@@ -129,30 +132,23 @@ private:
virtual void ValueNodeValueChanged(ValueNode* node);
private:
void _QueueEvent(Event* event);
void _PrepareToWaitForEvents(uint32 eventMask);
uint32 _WaitForEvents();
void _SignalInputLoop(uint32 events);
static const char* _GetPrompt(EditLine* editLine);
void _WaitForEvent(uint32 event);
private:
BLocker fLock;
Team* fTeam;
mutable BLocker fLock;
::Team* fTeam;
UserInterfaceListener* fListener;
ValueNodeManager* fNodeManager;
EditLine* fEditLine;
History* fHistory;
const char* fPrompt;
sem_id fBlockingSemaphore;
uint32 fInputLoopWaitingForEvents;
uint32 fEventsOccurred;
bool fInputLoopWaiting;
sem_id fWaitForEventSemaphore;
uint32 fEventOccurred;
volatile bool fTerminating;
BReference<Thread> fStoppedThread;
Thread* fCurrentThread;
BReference< ::Thread> fStoppedThread;
::Thread* fCurrentThread;
StackTrace* fCurrentStackTrace;
int32 fCurrentStackFrameIndex;
TeamMemoryBlock* fCurrentBlock;
@@ -160,8 +156,6 @@ private:
ExpressionInfo* fExpressionInfo;
status_t fExpressionResult;
ExpressionResult* fExpressionValue;
EventList fPendingEvents;
};
@@ -97,6 +97,7 @@ private:
CommandLineUserInterface::CommandLineUserInterface()
:
fContext(new CliContext()),
fCommands(20, true),
fShowSemaphore(-1),
fShown(false),
@@ -122,7 +123,7 @@ CommandLineUserInterface::ID() const
status_t
CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener)
{
status_t error = fContext.Init(team, listener);
status_t error = fContext->Init(team, listener);
if (error != B_OK)
return error;
@@ -152,7 +153,7 @@ CommandLineUserInterface::Terminate()
fTerminating = true;
if (fShown) {
fContext.Terminating();
fContext->Terminating();
// Wait for input loop to finish.
while (acquire_sem(fShowSemaphore) == B_INTERRUPTED) {
@@ -163,7 +164,10 @@ CommandLineUserInterface::Terminate()
fShowSemaphore = -1;
}
fContext.Cleanup();
fContext->Cleanup();
BMessage message(B_QUIT_REQUESTED);
fContext->PostMessage(&message);
}
@@ -236,6 +240,7 @@ CommandLineUserInterface::Run()
if (error != B_OK)
return;
fContext->Run();
_InputLoop();
// Release the Show() semaphore to signal Terminate().
release_sem(fShowSemaphore);
@@ -248,21 +253,19 @@ CommandLineUserInterface::_InputLoop()
thread_id currentThread = -1;
while (!fTerminating) {
fContext.ProcessPendingEvents();
// Wait for a thread or Ctrl-C.
fContext.WaitForThreadOrUser();
if (fContext.IsTerminating())
fContext->WaitForThreadOrUser();
if (fContext->IsTerminating())
break;
// Print the active thread, if it changed.
if (fContext.CurrentThreadID() != currentThread) {
fContext.PrintCurrentThread();
currentThread = fContext.CurrentThreadID();
if (fContext->CurrentThreadID() != currentThread) {
fContext->PrintCurrentThread();
currentThread = fContext->CurrentThreadID();
}
// read a command line
const char* line = fContext.PromptUser(kDebuggerPrompt);
const char* line = fContext->PromptUser(kDebuggerPrompt);
if (line == NULL)
break;
@@ -288,7 +291,7 @@ CommandLineUserInterface::_InputLoop()
continue;
// add line to history
fContext.AddLineToInputHistory(line);
fContext->AddLineToInputHistory(line);
// execute command
_ExecuteCommand(args.ArgumentCount(), args.Arguments());
@@ -369,7 +372,7 @@ CommandLineUserInterface::_ExecuteCommand(int argc, const char* const* argv)
{
CommandEntry* commandEntry = _FindCommand(argv[0]);
if (commandEntry != NULL)
commandEntry->Command()->Execute(argc, argv, fContext);
commandEntry->Command()->Execute(argc, argv, *fContext);
}
@@ -77,7 +77,7 @@ private:
const CommandEntry* command2);
private:
CliContext fContext;
CliContext* fContext;
CommandList fCommands;
sem_id fShowSemaphore;
bool fShown;
@@ -119,7 +119,7 @@ CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node,
while (node->LocationAndValueResolutionState()
== VALUE_NODE_UNRESOLVED) {
containerLocker.Unlock();
context.WaitForEvents(CliContext::EVENT_VALUE_NODE_CHANGED);
context.WaitForEvent(CliContext::MSG_VALUE_NODE_CHANGED);
containerLocker.Lock();
if (context.IsTerminating())
return B_ERROR;
@@ -46,7 +46,7 @@ CliStackTraceCommand::Execute(int argc, const char* const* argv,
// get its stack trace
StackTrace* stackTrace = thread->GetStackTrace();
while (stackTrace == NULL) {
context.WaitForEvents(CliContext::EVENT_THREAD_STACK_TRACE_CHANGED);
context.WaitForEvent(CliContext::MSG_THREAD_STACK_TRACE_CHANGED);
if (context.IsTerminating())
return;
stackTrace = thread->GetStackTrace();