GroveEngine/docs/plans/PROMPT_implement_deadlock_plan.md
StillHammer 97d579e142 docs: Add implementation prompt for deadlock prevention plan
Create comprehensive prompt for successor developer/agent to implement
the 15h deadlock detection & prevention plan.

Includes:
- Complete implementation roadmap (Semaine 1: Detection, Semaine 2: Prevention)
- Step-by-step commands for each phase
- Code examples BEFORE/AFTER
- Success criteria and validation checklist
- Debugging tips and common pitfalls
- Final report template

This prompt is fully autonomous - a fresh developer can execute the
entire plan following this guide.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 19:50:42 +08:00

17 KiB

Prompt : Implémentation du Plan Deadlock Detection & Prevention

Pour : Claude Code (successeur) ou développeur qui reprend ce plan Plan associé : PLAN_deadlock_detection_prevention.md Durée estimée : 15h sur 2 semaines Dernière mise à jour : 2025-01-21


🎯 Mission

Tu dois implémenter un système complet de détection et prévention des deadlocks pour GroveEngine, un moteur de jeu avec hot-reload de modules dynamiques en C++17.

Contexte :

  • GroveEngine utilise actuellement std::mutex avec std::lock_guard
  • Pattern : Single mutex par classe (risque faible mais amélioration nécessaire)
  • Un deadlock a été identifié dans test_13_cross_system (teste encore bloqué)
  • Le projet compile sur Linux/WSL2 avec CMake

Objectif final :

  1. Détection automatique des deadlocks (TSan + Helgrind)
  2. Prévention des deadlocks multi-mutex (scoped_lock)
  3. Optimisation concurrence read-heavy (shared_mutex)
  4. Tous les tests passent sans deadlock

📚 Documentation Requise

IMPORTANT : Lis ces documents avant de commencer :

  1. Plan complet : docs/plans/PLAN_deadlock_detection_prevention.md

    • Contient TOUTES les modifications ligne par ligne
    • Exemples de code AVANT/APRÈS
    • Commandes exactes à exécuter
  2. Tests d'intégration : docs/plans/PLAN_integration_tests_global.md

    • Liste des 13 tests à valider
    • Seuils de succès
  3. Architecture : docs/architecture/

    • Comprendre IntraIO, IntraIOManager, TopicTree
    • Flux de messages pub/sub

🗓️ Calendrier d'Implémentation

Semaine 1 : Détection (5h)

Jour 1-2 : ThreadSanitizer (2h)

Checklist :

  • Modifier CMakeLists.txt (copier le code du plan lignes 21-35)
  • Build avec TSan : cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan
  • Exécuter tous les tests : cd build-tsan && TSAN_OPTIONS="detect_deadlocks=1" ctest -V
  • Documenter les warnings TSan trouvés (créer docs/tsan_findings.md)
  • Fixer tous les lock-order-inversions détectés
  • Re-run tests jusqu'à 0 warning

Commandes :

# 1. Modifier CMakeLists.txt (copier du plan)
nano CMakeLists.txt

# 2. Build
cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan
cmake --build build-tsan -j$(nproc)

# 3. Test
cd build-tsan
TSAN_OPTIONS="detect_deadlocks=1 history_size=7 exitcode=1" ctest --output-on-failure

# 4. Si erreurs, voir logs
cat Testing/Temporary/LastTest.log

Critères de succès :

  • Build TSan compile sans erreurs
  • ctest retourne exit code 0
  • Aucun warning "lock-order-inversion"
  • Aucun warning "data race"

Jour 3-4 : Helgrind (3h)

Checklist :

  • Modifier CMakeLists.txt (copier code du plan lignes 84-126)
  • Créer helgrind.supp (copier du plan lignes 128-158)
  • Build : cmake -DGROVE_ENABLE_HELGRIND=ON -B build
  • Exécuter : cd build && make helgrind
  • Analyser helgrind-full.log
  • Ajouter suppressions pour false positives
  • Re-run jusqu'à log propre
  • Créer tableau comparatif TSan vs Helgrind

Commandes :

# 1. Créer helgrind.supp (copier du plan)
nano helgrind.supp

# 2. Modifier CMakeLists.txt
nano CMakeLists.txt

# 3. Build
cmake -DGROVE_ENABLE_HELGRIND=ON -B build
cmake --build build

# 4. Run Helgrind (LENT - 10-50x slowdown)
cd build
make helgrind

# 5. Analyser résultats
cat helgrind-full.log | grep -E "(Possible|lock order)" | less

# 6. Compter problèmes
cat helgrind-full.log | grep "Possible data race" | wc -l

Critères de succès :

  • Target make helgrind fonctionne
  • Fichier helgrind.supp avec suppressions
  • 0 lock order violations (après suppressions légitimes)
  • Tableau comparatif TSan vs Helgrind documenté

Semaine 2 : Prévention & Optimisation (10h)

Jour 5-7 : std::scoped_lock (4h)

Checklist :

  • Rechercher tous les lock_guard multi-mutex : grep -n "lock_guard" src/*.cpp | sort
  • Identifier les patterns : lock(mutex1) puis lock(mutex2) dans même fonction
  • Refactorer IntraIOManager.cpp lignes 176, 221, 256, 272, 329
  • Remplacer par std::scoped_lock(mutex1, mutex2)
  • Créer test unitaire tests/unit/test_scoped_lock.cpp (copier du plan)
  • Build et tester : cmake --build build && ctest
  • Valider avec TSan : aucun lock-order-inversion

Exemple de refactoring :

AVANT (src/IntraIOManager.cpp:176) :

void IntraIOManager::routeMessage(...) {
    std::lock_guard<std::mutex> lock(managerMutex);
    // ... code ...
    std::lock_guard<std::mutex> batchLock(batchMutex);  // ❌ Risque deadlock
}

APRÈS :

void IntraIOManager::routeMessage(...) {
    std::scoped_lock lock(managerMutex, batchMutex);  // ✅ Safe
    // ... code ...
}

Fichiers à modifier :

  1. src/IntraIOManager.cpp (5 endroits - voir plan lignes 213-234)
  2. tests/unit/test_scoped_lock.cpp (créer nouveau fichier - code dans plan lignes 236-283)
  3. docs/coding_guidelines.md (créer section - plan lignes 287-324)

Commandes :

# 1. Trouver tous les multi-mutex locks
grep -B3 -A3 "lock_guard" src/IntraIOManager.cpp

# 2. Modifier les fichiers (utilise ton éditeur)
nano src/IntraIOManager.cpp

# 3. Build et test
cmake --build build
ctest --output-on-failure

# 4. Validation TSan
cd build-tsan
cmake --build .
TSAN_OPTIONS="detect_deadlocks=1" ctest -V

Critères de succès :

  • Tous les lock_guard multi-mutex remplacés
  • Test test_scoped_lock passe
  • TSan validation : 0 lock-order-inversion
  • Documentation coding_guidelines.md créée

Jour 8-10 : std::shared_mutex (6h)

Checklist - TopicTree :

  • Modifier external/StillHammer/topictree/include/topictree/TopicTree.h ligne 56
  • Changer std::mutexstd::shared_mutex
  • Refactorer toutes les méthodes (voir plan lignes 406-478)
    • findSubscribers()std::shared_lock (READ)
    • registerSubscriber()std::unique_lock (WRITE)
    • unregisterSubscriber()std::unique_lock (WRITE)
    • clear()std::unique_lock (WRITE)
    • subscriberCount()std::shared_lock (READ)

Checklist - IntraIOManager :

  • Modifier include/grove/IntraIOManager.h
  • Split managerMutex en 2 : instancesMutex (shared) + statsMutex (exclusive)
  • Refactorer src/IntraIOManager.cpp (voir plan lignes 480-594)
    • getInstance()std::shared_lock (READ)
    • routeMessage()std::shared_lock pour lookup (CRITICAL!)
    • createInstance()std::unique_lock (WRITE)
    • removeInstance()std::unique_lock (WRITE)

Checklist - JsonDataTree (optionnel) :

  • Modifier include/grove/JsonDataTree.h et src/JsonDataTree.cpp
  • Changer std::mutexstd::shared_mutex
  • Refactorer méthodes (voir plan lignes 596-637)

Checklist - Benchmark :

  • Créer tests/benchmarks/benchmark_shared_mutex.cpp (plan lignes 641-688)
  • Ajouter au CMakeLists.txt (plan lignes 690-698)
  • Build : cmake --build build
  • Run : ./build/tests/benchmark_shared_mutex --benchmark_min_time=3s
  • Créer rapport docs/performance_reports/shared_mutex_results.md (plan lignes 718-772)

Commandes :

# 1. Modifier TopicTree.h
nano external/StillHammer/topictree/include/topictree/TopicTree.h

# 2. Modifier IntraIOManager
nano include/grove/IntraIOManager.h
nano src/IntraIOManager.cpp

# 3. Modifier JsonDataTree (optionnel)
nano include/grove/JsonDataTree.h
nano src/JsonDataTree.cpp

# 4. Créer benchmark
mkdir -p tests/benchmarks
nano tests/benchmarks/benchmark_shared_mutex.cpp

# 5. Modifier CMakeLists.txt pour benchmark
nano tests/CMakeLists.txt

# 6. Build
cmake --build build -j$(nproc)

# 7. Run tests
ctest --output-on-failure

# 8. Validation TSan (CRITIQUE!)
cd build-tsan
cmake --build .
TSAN_OPTIONS="detect_deadlocks=1" ctest -V

# 9. Run benchmark
cd ../build
./tests/benchmark_shared_mutex --benchmark_min_time=3s

# 10. Créer rapport de performance
mkdir -p docs/performance_reports
nano docs/performance_reports/shared_mutex_results.md

Résultats attendus du benchmark :

1 thread:  Overhead négligeable (~1%)
4 threads: Speedup 30-50x (mutex: 960ns → shared: 22ns)
8 threads: Speedup 150-250x (mutex: 7680ns → shared: 30ns)

Critères de succès :

  • TopicTree utilise shared_mutex
  • IntraIOManager split mutex (instances shared + stats exclusive)
  • JsonDataTree utilise shared_mutex (optionnel)
  • Benchmark créé et exécuté
  • Rapport de performance rempli (gain >50% démontré)
  • TSan validation : 0 data race
  • Tous les tests d'intégration passent

🔧 Outils et Commandes Essentielles

Build Variants

# Normal build
cmake -B build && cmake --build build

# TSan build (détection deadlock)
cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan
cmake --build build-tsan

# Helgrind build
cmake -DGROVE_ENABLE_HELGRIND=ON -B build
cmake --build build
cd build && make helgrind

Tests

# Tous les tests
ctest --output-on-failure

# Test spécifique
./tests/test_13_cross_system

# Avec TSan
TSAN_OPTIONS="detect_deadlocks=1 history_size=7" ./tests/test_13_cross_system

# Avec timeout (si deadlock)
timeout 30 ./tests/test_13_cross_system || echo "DEADLOCK DETECTED"

Debugging

# Voir les mutex actifs
ps aux | grep test_13
pstack <PID>  # Si disponible

# Logs TSan détaillés
TSAN_OPTIONS="detect_deadlocks=1 verbosity=2 log_path=tsan.log" ./test_13

# Analyser Helgrind
cat helgrind-full.log | grep -A10 "lock order"

⚠️ Pièges à Éviter

1. Test 13 Deadlock (ligne 333)

Problème identifié :

// test_13_cross_system.cpp:331-333
auto dataRootPtr = tree->getDataRootReadOnly();  // ❌ Raw pointer
dataRootPtr->setChild("player", ...);  // ❌ Modification via read-only!

Fix :

auto dataRoot = tree->getDataRoot();  // ✅ Writable unique_ptr
dataRoot->setChild("player", std::move(player5));

2. TSan False Positives

Si TSan rapporte des races sur :

  • spdlog : Ajouter à suppressions (lazy init benign)
  • std::atomic : Normal, TSan ne comprend pas toujours
  • Thread creation/join : Benign

Ne supprime PAS :

  • Lock-order-inversion : VRAI problème!
  • Data race sur variables non-atomic : VRAI problème!

3. Helgrind Lenteur

  • 10-50x slowdown est NORMAL
  • Test complet peut prendre 1-2h
  • Utilise make helgrind-single pour tester un seul test
  • Patience!

4. shared_mutex Performance

  • Vérifie le ratio Read/Write : doit être >10:1
  • Si writes fréquents (>30%), shared_mutex est PLUS LENT
  • TopicTree : OK (100:1 ratio)
  • IntraIOManager : OK (50:1 ratio)
  • Stats counters : NON (1:1 ratio) → garde std::mutex

📋 Checklist Finale de Validation

Avant de considérer le plan terminé, vérifie :

Phase 1 : Détection

  • CMakeLists.txt avec options GROVE_ENABLE_TSAN et GROVE_ENABLE_HELGRIND
  • Build TSan compile et tests passent (exit code 0)
  • Build Helgrind targets fonctionnent (make helgrind)
  • Fichier helgrind.supp avec suppressions appropriées
  • 0 lock-order-inversion dans TSan output
  • 0 data race dans TSan output
  • Documentation TSan vs Helgrind (tableau comparatif)

Phase 2 : Prévention

  • Tous les lock_guard multi-mutex → scoped_lock
  • Test unitaire test_scoped_lock.cpp passe
  • Documentation coding_guidelines.md mise à jour
  • TSan validation : 0 warning

Phase 3 : Optimisation

  • TopicTree.h utilise std::shared_mutex
  • IntraIOManager split instancesMutex (shared) + statsMutex (exclusive)
  • JsonDataTree utilise std::shared_mutex (si applicable)
  • Benchmark benchmark_shared_mutex créé et exécuté
  • Rapport de performance avec gains >50% documenté
  • TSan validation : 0 data race
  • Tous les 13 tests d'intégration passent

Tests Critiques

  • test_01_production_hotreload : PASS
  • test_02_chaos_monkey : PASS
  • test_03_stress_test : PASS (10 min)
  • test_04_race_condition : PASS
  • test_13_cross_system : PASS (fix deadlock ligne 333)

Documentation

  • docs/tsan_findings.md créé
  • docs/coding_guidelines.md mis à jour
  • docs/performance_reports/shared_mutex_results.md créé
  • README.md des plans mis à jour (statut 🟢)

🎯 Critères de Succès Final

Le plan est TERMINÉ quand :

  1. Build TSan : cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan && cd build-tsan && TSAN_OPTIONS="detect_deadlocks=1" ctest

    • Exit code: 0
    • Output: "100% tests passed, 0 tests failed"
    • Aucun warning TSan
  2. Build Helgrind : cd build && make helgrind

    • Exit code: 0
    • helgrind-full.log propre (après suppressions)
  3. Tests d'intégration : ctest --output-on-failure

    • 13/13 tests passent
    • Dont test_13_cross_system (fix deadlock)
  4. Benchmark : ./tests/benchmark_shared_mutex

    • Speedup >50% démontré (4 threads)
    • Rapport de performance documenté
  5. Code Review :

    • Aucun lock_guard multi-mutex restant
    • Tous les read-heavy locks sont shared_lock
    • Tous les write locks sont unique_lock

📞 En Cas de Problème

Test 13 deadlock toujours présent

# 1. Identifier où ça bloque
timeout 10 ./tests/test_13_cross_system
ps aux | grep test_13
pstack <PID>  # Voir les stacks

# 2. Vérifier le fix ligne 333
grep -n "getDataRootReadOnly" tests/integration/test_13_cross_system.cpp
# Doit utiliser getDataRoot() au lieu de getDataRootReadOnly()

# 3. Rebuild et retest
cmake --build build
./tests/test_13_cross_system

TSan trouve encore des lock-order-inversions

# 1. Voir exactement où
TSAN_OPTIONS="detect_deadlocks=1 history_size=7 second_deadlock_stack=1" ./problematic_test

# 2. Identifier les mutexes (M1, M2)
# 3. Utiliser scoped_lock(M1, M2) partout
# 4. Rebuild et retest

Helgrind timeout

# 1. Run un seul test
make helgrind-single

# 2. Si trop lent, skip Helgrind
# TSan est suffisant pour validation

Benchmark ne montre pas de gain

# 1. Vérifier le ratio read/write
# Si writes > 30%, shared_mutex est inutile

# 2. Vérifier que tu as bien utilisé shared_lock pour les reads
grep "shared_lock" src/IntraIOManager.cpp

# 3. Run benchmark avec plus de threads
./benchmark_shared_mutex --benchmark_filter=.*MultiThread.*/threads:8

📝 Rapport Final à Produire

Quand tout est terminé, crée : docs/plans/REPORT_deadlock_plan_completed.md

Template :

# Rapport : Plan Deadlock Detection & Prevention - TERMINÉ

**Date de complétion** : YYYY-MM-DD
**Durée réelle** : Xh (estimé: 15h)
**Statut** : ✅ TERMINÉ

## Résumé

[1-2 paragraphes résumant ce qui a été fait]

## Phase 1 : Détection (5h)

- ✅ ThreadSanitizer intégré (2h réelles)
  - Warnings TSan trouvés : X
  - Fixes appliqués : Y
- ✅ Helgrind intégré (3h réelles)
  - Suppressions ajoutées : Z

## Phase 2 : Prévention (4h)

- ✅ scoped_lock refactoring (4h réelles)
  - Fichiers modifiés : X
  - Lock_guard → scoped_lock : Y endroits

## Phase 3 : Optimisation (6h)

- ✅ shared_mutex implémenté (6h réelles)
  - TopicTree : ✅
  - IntraIOManager : ✅
  - JsonDataTree : ✅/❌
  - Speedup mesuré : Xx (4 threads), Yy (8 threads)

## Tests Validation

| Test | Avant | Après | Statut |
|------|-------|-------|--------|
| test_01 | ✅ | ✅ | OK |
| test_02 | ✅ | ✅ | OK |
| ... | ... | ... | ... |
| test_13 | ❌ Deadlock | ✅ | FIXED |

## Benchmark Results

[Copier les résultats du benchmark]

## Problèmes Rencontrés

1. [Problème 1 et solution]
2. [Problème 2 et solution]

## Leçons Apprises

[Ce qui a été appris pendant l'implémentation]

## Recommandations Futures

1. [Amélioration 1]
2. [Amélioration 2]

🚀 Let's Go!

Tu as maintenant TOUT ce qu'il faut :

  • Plan détaillé (30KB de specs)
  • Code AVANT/APRÈS ligne par ligne
  • Commandes exactes
  • Tests de validation
  • Debugging tips
  • Checklist complète

Commence par la Phase 1.1 (ThreadSanitizer - 2h) :

# 1. Ouvre le plan
cat docs/plans/PLAN_deadlock_detection_prevention.md

# 2. Copie le code CMake (lignes 21-35)
nano CMakeLists.txt

# 3. Build
cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan
cmake --build build-tsan

# 4. Test
cd build-tsan
TSAN_OPTIONS="detect_deadlocks=1" ctest -V

# 5. Fix tous les warnings
# 6. Re-test jusqu'à 0 warning

Bonne chance ! 🎯


Auteur : Claude Code Version : 1.0 Pour : Successeur/Implémenteur du plan deadlock Date : 2025-01-21