Chromium Chronicle #25: annotations de sécurité des fils de discussion

Épisode 25:de Victor Costan à San Francisco (octobre 2021)
Épisodes précédents

En C++, l'exclusion de l'éventualité d'une concurrence des données se résume à une petite preuve d'exactitude de la sécurité des threads pour chaque accès de membre de données. Ces preuves s'accompagnent d'une grande charge mentale, en particulier lorsque vous examinez ou refactorisez du code. Le framework d'analyse statique de Clang prend en charge les tâches répétitives liées aux preuves de la sécurité des threads.

Ajouter GUARDED_BY_CONTEXT() aux membres de données dans les classes non sécurisées aux threads

La plupart des classes Chrome ne sont pas sécurisées et doivent être utilisées dans une seule séquence. Ajoutez des annotations à tous les membres de données qui ne sont pas sécurisés. Les annotations inutiles sont sûres, mais les annotations manquantes présentent un risque de concurrence entre les données.

#include "base/sequence_checker.h"  // for SEQUENCE_CHECKER()
#include "base/thread_annotations.h"  // for GUARDED_BY_CONTEXT()

class Cache {
  // Methods here.
 private:
  SEQUENCE_CHECKER(sequence_checker_);
  base::flat_map<std::string, std::string> data_ GUARDED_BY_CONTEXT(sequence_checker_);
};

Clang applique des vérifications de séquence

En échange de l'annotation des membres des données, Clang s'assure que toute méthode qui accède aux données effectue un contrôle de sécurité de séquence avant de le faire. À mesure que le code est déplacé lors des refactorisations, Clang continue d'appliquer l'annotation GUARDED_BY_CONTEXT().

void Cache::Set(base::StringPiece key, base::StringPiece value) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);  // Clang warns without this.
  data_.emplace(key, value);
}

Ajouter GUARDED_BY() aux membres de données des classes thread-safe qui utilisent des mutex

Certaines classes dans Chrome doivent utiliser des verrous pour la sécurité des threads. Dans ce cas, annotez tous les membres de données qui ne sont pas sécurisés. Chaque annotation pointe vers un mutex qui doit être maintenu pendant l'accès au membre des données.

#include "base/thread_annotations.h"  // for GUARDED_BY()

class ThreadSafeCache {
  // Methods here.
  private:
    base::Lock lock_;
    base::flat_map<std::string, std::string> data_ GUARDED_BY(lock_);
};

Clang impose les acquisitions de verrous

Patientez et laissez le compilateur s'assurer que le champ d'application de chaque base::AutoLock est correct. et qui verrouillent les appels Acquire() et Release() sont associés correctement.

void ThreadSafeCache::Set(base::StringPiece key, base::StringPiece value) {
  base::AutoLock auto_lock(lock_);  // Clang warns without this.
  data_.emplace(key, value);
}