From 25c2d5616eb5065a69043bbf3e78817f6870a15f Mon Sep 17 00:00:00 2001
From: Rene Gollent <anevilyak@gmail.com>
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.
---
src/apps/debugger/controllers/TeamDebugger.cpp | 106 +++++++++++++++++++++++-
src/apps/debugger/controllers/TeamDebugger.h | 7 ++
2 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp
index 923f3d3..6d84455 100644
a
|
b
|
struct TeamDebugger::ImageHandlerHashDefinition {
|
130 | 130 | }; |
131 | 131 | |
132 | 132 | |
| 133 | // #pragma mark - ImageInfoPendingThread |
| 134 | |
| 135 | |
| 136 | struct TeamDebugger::ImageInfoPendingThread { |
| 137 | public: |
| 138 | ImageInfoPendingThread(image_id image, thread_id thread) |
| 139 | : |
| 140 | fImage(image), |
| 141 | fThread(thread) |
| 142 | { |
| 143 | } |
| 144 | |
| 145 | ~ImageInfoPendingThread() |
| 146 | { |
| 147 | } |
| 148 | |
| 149 | image_id ImageID() const |
| 150 | { |
| 151 | return fImage; |
| 152 | } |
| 153 | |
| 154 | thread_id ThreadID() const |
| 155 | { |
| 156 | return fThread; |
| 157 | } |
| 158 | |
| 159 | private: |
| 160 | image_id fImage; |
| 161 | thread_id fThread; |
| 162 | |
| 163 | public: |
| 164 | ImageInfoPendingThread* |
| 165 | fNext; |
| 166 | }; |
| 167 | |
| 168 | |
| 169 | // #pragma mark - ImageHandlerHashDefinition |
| 170 | |
| 171 | |
| 172 | struct TeamDebugger::ImageInfoPendingThreadHashDefinition { |
| 173 | typedef image_id KeyType; |
| 174 | typedef ImageInfoPendingThread |
| 175 | ValueType; |
| 176 | |
| 177 | size_t HashKey(image_id key) const |
| 178 | { |
| 179 | return (size_t)key; |
| 180 | } |
| 181 | |
| 182 | size_t Hash(const ImageInfoPendingThread* value) const |
| 183 | { |
| 184 | return HashKey(value->ImageID()); |
| 185 | } |
| 186 | |
| 187 | bool Compare(image_id key, const ImageInfoPendingThread* value) const |
| 188 | { |
| 189 | return value->ImageID() == key; |
| 190 | } |
| 191 | |
| 192 | ImageInfoPendingThread*& GetLink(ImageInfoPendingThread* value) const |
| 193 | { |
| 194 | return value->fNext; |
| 195 | } |
| 196 | }; |
| 197 | |
| 198 | |
133 | 199 | // #pragma mark - TeamDebugger |
134 | 200 | |
135 | 201 | |
… |
… |
TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface,
|
142 | 208 | fTeam(NULL), |
143 | 209 | fTeamID(-1), |
144 | 210 | fImageHandlers(NULL), |
| 211 | fImageInfoPendingThreads(NULL), |
145 | 212 | fDebuggerInterface(NULL), |
146 | 213 | fFileManager(NULL), |
147 | 214 | fWorker(NULL), |
… |
… |
TeamDebugger::~TeamDebugger()
|
204 | 271 | |
205 | 272 | delete fImageHandlers; |
206 | 273 | |
| 274 | if (fImageInfoPendingThreads != NULL) { |
| 275 | ImageInfoPendingThread* thread = fImageInfoPendingThreads->Clear(true); |
| 276 | while (thread != NULL) { |
| 277 | ImageInfoPendingThread* next = thread->fNext; |
| 278 | delete thread; |
| 279 | thread = next; |
| 280 | } |
| 281 | } |
| 282 | delete fImageInfoPendingThreads; |
| 283 | |
207 | 284 | delete fBreakpointManager; |
208 | 285 | delete fWatchpointManager; |
209 | 286 | delete fMemoryBlockManager; |
… |
… |
TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
295 | 372 | if (error != B_OK) |
296 | 373 | return error; |
297 | 374 | |
| 375 | fImageInfoPendingThreads = new(std::nothrow) ImageInfoPendingThreadTable; |
| 376 | if (fImageInfoPendingThreads == NULL) |
| 377 | return B_NO_MEMORY; |
| 378 | |
298 | 379 | // create our worker |
299 | 380 | fWorker = new(std::nothrow) Worker; |
300 | 381 | if (fWorker == NULL) |
… |
… |
TeamDebugger::_HandleImageCreated(ImageCreatedEvent* event)
|
1209 | 1290 | { |
1210 | 1291 | AutoLocker< ::Team> locker(fTeam); |
1211 | 1292 | _AddImage(event->GetImageInfo()); |
1212 | | return false; |
| 1293 | |
| 1294 | ImageInfoPendingThread* info = new(std::nothrow) ImageInfoPendingThread( |
| 1295 | event->GetImageInfo().ImageID(), event->Thread()); |
| 1296 | if (info == NULL) |
| 1297 | return false; |
| 1298 | |
| 1299 | fImageInfoPendingThreads->Insert(info); |
| 1300 | return true; |
1213 | 1301 | } |
1214 | 1302 | |
1215 | 1303 | |
… |
… |
TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
|
1249 | 1337 | |
1250 | 1338 | locker.Unlock(); |
1251 | 1339 | |
1252 | | // update breakpoints in the image |
1253 | | fBreakpointManager->UpdateImageBreakpoints(image); |
| 1340 | image_debug_info_state state = image->ImageDebugInfoState(); |
| 1341 | if (state == IMAGE_DEBUG_INFO_LOADED |
| 1342 | || state == IMAGE_DEBUG_INFO_UNAVAILABLE) { |
| 1343 | // update breakpoints in the image |
| 1344 | fBreakpointManager->UpdateImageBreakpoints(image); |
| 1345 | |
| 1346 | ImageInfoPendingThread* thread = fImageInfoPendingThreads |
| 1347 | ->Lookup(imageID); |
| 1348 | if (thread != NULL) { |
| 1349 | fDebuggerInterface->ContinueThread(thread->ThreadID()); |
| 1350 | fImageInfoPendingThreads->Remove(thread); |
| 1351 | delete thread; |
| 1352 | } |
| 1353 | } |
1254 | 1354 | } |
1255 | 1355 | |
1256 | 1356 | |
diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h
index 378038b..a605718 100644
a
|
b
|
private:
|
103 | 103 | private: |
104 | 104 | struct ImageHandler; |
105 | 105 | struct ImageHandlerHashDefinition; |
| 106 | struct ImageInfoPendingThread; |
| 107 | struct ImageInfoPendingThreadHashDefinition; |
| 108 | |
106 | 109 | typedef BOpenHashTable<ImageHandlerHashDefinition> ImageHandlerTable; |
| 110 | typedef BOpenHashTable<ImageInfoPendingThreadHashDefinition> |
| 111 | ImageInfoPendingThreadTable; |
107 | 112 | |
108 | 113 | private: |
109 | 114 | static status_t _DebugEventListenerEntry(void* data); |
… |
… |
private:
|
166 | 171 | ThreadHandlerTable fThreadHandlers; |
167 | 172 | // protected by the team lock |
168 | 173 | ImageHandlerTable* fImageHandlers; |
| 174 | ImageInfoPendingThreadTable* |
| 175 | fImageInfoPendingThreads; |
169 | 176 | DebuggerInterface* fDebuggerInterface; |
170 | 177 | TeamDebugInfo* fTeamDebugInfo; |
171 | 178 | FileManager* fFileManager; |