229 lines
7.4 KiB
Markdown
229 lines
7.4 KiB
Markdown
# DEADLOCK FIX STATUS - PHASE 3 ANALYSIS COMPLETE ✅
|
|||
|
|
|
||
|
|
## COMPREHENSIVE AUDIT FINDINGS
|
||
|
|
|
||
|
|
### Total ObjectAccessor Calls from Worker Threads: **31 calls**
|
||
|
|
|
||
|
|
**Systems Affected**:
|
||
|
|
- ✅ TargetScanner (3 calls) - **FIXED**
|
||
|
|
- ⚠️ ClassAI (5 calls) - **PARTIALLY FIXED** (UnholySpecialization done, EvokerAI done)
|
||
|
|
- ❌ QuestManager (11 calls) - **AUTOMATED FIX INCOMPLETE**
|
||
|
|
- ❌ GatheringManager (5 calls) - **AUTOMATED FIX INCOMPLETE**
|
||
|
|
- ❌ Strategy Systems (10 calls) - **AUTOMATED FIX INCOMPLETE**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## PHASE 1: TargetScanner (COMPLETE ✅)
|
||
|
|
|
||
|
|
**ROOT CAUSE ELIMINATED**: TargetScanner methods no longer access Map from worker threads
|
||
|
|
|
||
|
|
**Files Fixed**:
|
||
|
|
1. `TargetScanner.h` - Changed return types to ObjectGuid
|
||
|
|
- FindNearestHostile() → ObjectGuid
|
||
|
|
- FindBestTarget() → ObjectGuid
|
||
|
|
- FindAllHostiles() → std::vector<ObjectGuid>
|
||
|
|
|
||
|
|
2. `TargetScanner.cpp` - Eliminated ObjectAccessor::GetUnit() calls
|
||
|
|
- FindAllHostiles: Returns GUIDs from snapshot data (line 249-337)
|
||
|
|
- FindBestTarget: Priority calculation using snapshot data (line 183-264)
|
||
|
|
- FindNearestHostile: Distance calculation using snapshot data (line 128-181)
|
||
|
|
|
||
|
|
3. `BotAI.cpp` - Updated caller to resolve GUIDs on main thread (line 948-958)
|
||
|
|
- Gets ObjectGuid from FindBestTarget()
|
||
|
|
- Resolves GUID → Unit* on main thread (safe)
|
||
|
|
- Validates before engaging
|
||
|
|
|
||
|
|
**Impact**: MASSIVE - TargetScanner is called hundreds of times per second across thousands of bots
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## PHASE 2: ClassAI Critical Methods (COMPLETE ✅)
|
||
|
|
|
||
|
|
**Files Fixed**:
|
||
|
|
1. `DeathKnights/UnholySpecialization.h/cpp`
|
||
|
|
- UpdateGhoulManagement: Now accepts target parameter (line 1555)
|
||
|
|
- CommandGhoulIfNeeded: Now accepts target parameter (line 1603)
|
||
|
|
- HandleEmergencySurvival: Now accepts target parameter (fixed)
|
||
|
|
- UpdateCombatPhase: Now accepts target parameter (fixed)
|
||
|
|
- Eliminated ObjectAccessor call from worker thread
|
||
|
|
|
||
|
|
2. `Evokers/EvokerAI.h/cpp`
|
||
|
|
- UpdateEssenceManagement: Now accepts target parameter (line 656)
|
||
|
|
- Eliminated ObjectAccessor calls from worker thread
|
||
|
|
|
||
|
|
**Impact**: SIGNIFICANT - These methods run on worker threads for every bot update
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## PHASE 3: Quest/Gathering/Strategy Systems (ANALYSIS COMPLETE)
|
||
|
|
|
||
|
|
### CRITICAL DISCOVERY: DEEPER REFACTORING NEEDED
|
||
|
|
|
||
|
|
**Problem**: Automated script replaced ObjectAccessor calls but **code logic still depends on pointers throughout method bodies**
|
||
|
|
|
||
|
|
**Example**:
|
||
|
|
```cpp
|
||
|
|
// AUTOMATED FIX (BROKEN):
|
||
|
|
ObjectGuid creatureGuid = guid; // Replaced ObjectAccessor call
|
||
|
|
if (!creature || creature->isDead()) // ERROR: creature undefined!
|
||
|
|
continue;
|
||
|
|
```
|
||
|
|
|
||
|
|
**Files Affected**:
|
||
|
|
- QuestCompletion.cpp (20 compilation errors)
|
||
|
|
- QuestPickup.cpp (automated fix incomplete)
|
||
|
|
- QuestTurnIn.cpp (automated fix incomplete)
|
||
|
|
- GatheringManager.cpp (automated fix incomplete)
|
||
|
|
- LootStrategy.cpp (automated fix incomplete)
|
||
|
|
- QuestStrategy.cpp (1 compilation error)
|
||
|
|
- CombatMovementStrategy.cpp (automated fix incomplete)
|
||
|
|
|
||
|
|
### TWO SOLUTIONS AVAILABLE
|
||
|
|
|
||
|
|
#### **Option A: Complete Snapshot Integration** (4-6 hours)
|
||
|
|
- Enhance DoubleBufferedSpatialGrid with GameObject snapshots
|
||
|
|
- Add quest/gathering fields to CreatureSnapshot
|
||
|
|
- Manually refactor ALL 31 methods to use snapshots
|
||
|
|
- **Pros**: Complete thread-safe solution, future-proof
|
||
|
|
- **Cons**: Time-consuming, complex logic changes
|
||
|
|
|
||
|
|
#### **Option B: Main Thread Execution** (30 minutes) ⭐ RECOMMENDED
|
||
|
|
- Move UpdateManagers() from BotAI::UpdateAI() to World::Update()
|
||
|
|
- Quest/Gathering/Strategy execute on MAIN THREAD
|
||
|
|
- ObjectAccessor calls become SAFE (main thread has Map access)
|
||
|
|
- **Pros**: Quick, eliminates deadlock immediately, proven pattern
|
||
|
|
- **Cons**: Not "pure" thread-safe, managers run on main thread
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## RECOMMENDATION: OPTION B
|
||
|
|
|
||
|
|
### Why Option B is Better RIGHT NOW:
|
||
|
|
|
||
|
|
1. **Immediate Results**: Can test with 5000+ bots TODAY
|
||
|
|
2. **Proven TrinityCore Pattern**: Manager updates on main thread is standard
|
||
|
|
3. **Preserves Combat Performance**: ClassAI rotations still run on worker threads
|
||
|
|
4. **Low Risk**: Minimal code changes, no complex refactoring
|
||
|
|
5. **Iterative Improvement**: Can still do Option A later as enhancement
|
||
|
|
|
||
|
|
### Implementation Plan for Option B:
|
||
|
|
|
||
|
|
**Step 1**: Revert automated Quest/Gathering/Strategy changes
|
||
|
|
```bash
|
||
|
|
git checkout -- src/modules/Playerbot/Quest/
|
||
|
|
git checkout -- src/modules/Playerbot/Professions/GatheringManager.cpp
|
||
|
|
git checkout -- src/modules/Playerbot/AI/Strategy/
|
||
|
|
```
|
||
|
|
|
||
|
|
**Step 2**: Move UpdateManagers() to main thread
|
||
|
|
|
||
|
|
**File**: `BotAI.cpp` line 502
|
||
|
|
```cpp
|
||
|
|
// REMOVE UpdateManagers(diff) from BotAI::UpdateAI()
|
||
|
|
```
|
||
|
|
|
||
|
|
**File**: `World.cpp` after line 2356 (after bot actions, before Map updates)
|
||
|
|
```cpp
|
||
|
|
// Process bot manager updates on MAIN THREAD
|
||
|
|
{
|
||
|
|
TC_METRIC_TIMER("world_update_time", TC_METRIC_TAG("type", "Bot Manager Updates"));
|
||
|
|
if (sPlayerBotMgr)
|
||
|
|
sPlayerBotMgr->UpdateAllBotManagers(diff);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**File**: `PlayerBotMgr.h`
|
||
|
|
```cpp
|
||
|
|
void UpdateAllBotManagers(uint32 diff);
|
||
|
|
```
|
||
|
|
|
||
|
|
**File**: `PlayerBotMgr.cpp`
|
||
|
|
```cpp
|
||
|
|
void PlayerBotMgr::UpdateAllBotManagers(uint32 diff)
|
||
|
|
{
|
||
|
|
for (auto& [guid, bot] : _bots)
|
||
|
|
{
|
||
|
|
if (BotAI* ai = bot->GetBotAI())
|
||
|
|
ai->UpdateManagers(diff);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Step 3**: Build and test
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## WHAT RUNS WHERE (AFTER OPTION B)
|
||
|
|
|
||
|
|
### Worker Threads (Thread Pool):
|
||
|
|
- ✅ BotAI::UpdateAI() - Main AI logic
|
||
|
|
- ✅ ClassAI::UpdateRotation() - Combat rotations (TargetScanner returns GUIDs safely)
|
||
|
|
- ✅ Movement updates
|
||
|
|
- ✅ Behavior priority processing
|
||
|
|
- ✅ Strategy trigger evaluation
|
||
|
|
|
||
|
|
### Main Thread (World::Update):
|
||
|
|
- ✅ Bot action processing (BotActionProcessor)
|
||
|
|
- ✅ **QuestManager::Update()** - Safe ObjectAccessor usage
|
||
|
|
- ✅ **GatheringManager::Update()** - Safe ObjectAccessor usage
|
||
|
|
- ✅ **TradeManager::Update()** - Safe ObjectAccessor usage
|
||
|
|
- ✅ **AuctionManager::Update()** - Safe ObjectAccessor usage
|
||
|
|
- ✅ **Strategy execution** - Safe ObjectAccessor usage
|
||
|
|
- ✅ Map::Update()
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## TESTING CHECKLIST (AFTER OPTION B)
|
||
|
|
|
||
|
|
- [ ] Revert automated Quest/Gathering/Strategy changes
|
||
|
|
- [ ] Implement PlayerBotMgr::UpdateAllBotManagers()
|
||
|
|
- [ ] Move UpdateManagers() call to World::Update()
|
||
|
|
- [ ] Build succeeds
|
||
|
|
- [ ] Spawn 100 bots - verify futures complete
|
||
|
|
- [ ] Spawn 1000 bots - verify futures complete
|
||
|
|
- [ ] Spawn 5000 bots - **CRITICAL TEST: futures 3-14 MUST complete**
|
||
|
|
- [ ] Monitor for 60-second hangs - **MUST BE ZERO**
|
||
|
|
- [ ] Verify quest operations work
|
||
|
|
- [ ] Verify gathering operations work
|
||
|
|
- [ ] Verify combat rotations work
|
||
|
|
- [ ] Check server logs for deadlock warnings
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## COMPILATION STATUS
|
||
|
|
|
||
|
|
**Current**: ❌ 20+ errors in Quest/Strategy files (automated fix incomplete)
|
||
|
|
|
||
|
|
**Files Compiling**:
|
||
|
|
- ✅ TargetScanner.cpp
|
||
|
|
- ✅ TargetScanner.h
|
||
|
|
- ✅ BotAI.cpp
|
||
|
|
- ✅ UnholySpecialization.cpp
|
||
|
|
- ✅ UnholySpecialization.h
|
||
|
|
- ✅ EvokerAI.cpp
|
||
|
|
- ✅ EvokerAI.h
|
||
|
|
|
||
|
|
**Files Failing**:
|
||
|
|
- ❌ QuestCompletion.cpp (20 errors - uses undefined 'creature' pointer)
|
||
|
|
- ❌ QuestStrategy.cpp (1 error - uses undefined 'gameObject' pointer)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SUMMARY
|
||
|
|
|
||
|
|
**ANALYSIS COMPLETE**: All 31 ObjectAccessor calls identified and documented
|
||
|
|
|
||
|
|
**OPTION B RECOMMENDED**: Move manager updates to main thread (30 min implementation)
|
||
|
|
|
||
|
|
**EXPECTED OUTCOME**: 100% deadlock elimination, futures 3-14 complete with 5000+ bots
|
||
|
|
|
||
|
|
**NEXT STEP**: Implement Option B OR choose Option A for complete snapshot integration
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## DOCUMENTATION FILES
|
||
|
|
|
||
|
|
- `COMPLETE_DEADLOCK_AUDIT.md` - Full audit of all 31 ObjectAccessor calls
|
||
|
|
- `DEADLOCK_FIX_PHASE3_STATUS.md` - Detailed status and recommendations
|
||
|
|
- `fix_all_objectaccessor_deadlocks.py` - Automated fix script (incomplete for Quest/Gathering/Strategy)
|