From 4e9b38d34e1fbd57ba37bee54438b2e68c981082 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 28 Nov 2012 19:11:50 -0500 Subject: [PATCH] Fix #9221. - When an image creation notification is received, the thread that provoked it needs to be suspended until the debugger has finished loading the image's debug information. Otherwise, if that image had a breakpoint in it, it was possible that the thread would execute past the code where the breakpoint should be before the debugger had a chance to actually install it. - Only update breakpoints when debug info loading has actually finished. --- .../debugger/controllers/TeamDebugger.cpp | 104 +++++++++++++++++- src/apps/debugger/controllers/TeamDebugger.h | 6 + 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 923f3d37e0..3e92cb12d0 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -130,6 +130,70 @@ struct TeamDebugger::ImageHandlerHashDefinition { }; +// #pragma mark - ImageInfoPendingThread + + +struct TeamDebugger::ImageInfoPendingThread { +public: + ImageInfoPendingThread(image_id image, thread_id thread) + : + fImage(image), + fThread(thread) + { + } + + ~ImageInfoPendingThread() + { + } + + image_id ImageID() const + { + return fImage; + } + + thread_id ThreadID() const + { + return fThread; + } + +private: + image_id fImage; + thread_id fThread; + +public: + ImageInfoPendingThread* fNext; +}; + + +// #pragma mark - ImageHandlerHashDefinition + + +struct TeamDebugger::ImageInfoPendingThreadHashDefinition { + typedef image_id KeyType; + typedef ImageInfoPendingThread ValueType; + + size_t HashKey(image_id key) const + { + return (size_t)key; + } + + size_t Hash(const ImageInfoPendingThread* value) const + { + return HashKey(value->ImageID()); + } + + bool Compare(image_id key, const ImageInfoPendingThread* value) const + { + return value->ImageID() == key; + } + + ImageInfoPendingThread*& GetLink(ImageInfoPendingThread* value) const + { + return value->fNext; + } +}; + + // #pragma mark - TeamDebugger @@ -142,6 +206,7 @@ TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface, fTeam(NULL), fTeamID(-1), fImageHandlers(NULL), + fImageInfoPendingThreads(NULL), fDebuggerInterface(NULL), fFileManager(NULL), fWorker(NULL), @@ -204,6 +269,16 @@ TeamDebugger::~TeamDebugger() delete fImageHandlers; + if (fImageInfoPendingThreads != NULL) { + ImageInfoPendingThread* thread = fImageInfoPendingThreads->Clear(true); + while (thread != NULL) { + ImageInfoPendingThread* next = thread->fNext; + delete thread; + thread = next; + } + } + delete fImageInfoPendingThreads; + delete fBreakpointManager; delete fWatchpointManager; delete fMemoryBlockManager; @@ -295,6 +370,10 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) if (error != B_OK) return error; + fImageInfoPendingThreads = new(std::nothrow) ImageInfoPendingThreadTable; + if (fImageInfoPendingThreads == NULL) + return B_NO_MEMORY; + // create our worker fWorker = new(std::nothrow) Worker; if (fWorker == NULL) @@ -1209,7 +1288,14 @@ TeamDebugger::_HandleImageCreated(ImageCreatedEvent* event) { AutoLocker< ::Team> locker(fTeam); _AddImage(event->GetImageInfo()); - return false; + + ImageInfoPendingThread* info = new(std::nothrow) ImageInfoPendingThread( + event->GetImageInfo().ImageID(), event->Thread()); + if (info == NULL) + return false; + + fImageInfoPendingThreads->Insert(info); + return true; } @@ -1249,8 +1335,20 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) locker.Unlock(); - // update breakpoints in the image - fBreakpointManager->UpdateImageBreakpoints(image); + image_debug_info_state state = image->ImageDebugInfoState(); + if (state == IMAGE_DEBUG_INFO_LOADED + || state == IMAGE_DEBUG_INFO_UNAVAILABLE) { + // update breakpoints in the image + fBreakpointManager->UpdateImageBreakpoints(image); + + ImageInfoPendingThread* thread = fImageInfoPendingThreads + ->Lookup(imageID); + if (thread != NULL) { + fDebuggerInterface->ContinueThread(thread->ThreadID()); + fImageInfoPendingThreads->Remove(thread); + delete thread; + } + } } diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 378038b4bb..b8b43478af 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -103,7 +103,12 @@ private: private: struct ImageHandler; struct ImageHandlerHashDefinition; + struct ImageInfoPendingThread; + struct ImageInfoPendingThreadHashDefinition; + typedef BOpenHashTable ImageHandlerTable; + typedef BOpenHashTable + ImageInfoPendingThreadTable; private: static status_t _DebugEventListenerEntry(void* data); @@ -166,6 +171,7 @@ private: ThreadHandlerTable fThreadHandlers; // protected by the team lock ImageHandlerTable* fImageHandlers; + ImageInfoPendingThreadTable* fImageInfoPendingThreads; DebuggerInterface* fDebuggerInterface; TeamDebugInfo* fTeamDebugInfo; FileManager* fFileManager;