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

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

En C++, écarter la possibilité d'un conflit de données se résume à une petite preuve de l'exactitude de la sécurité des threads pour chaque accès des membres des données. Ces preuves s'ajoutent à beaucoup de tâches mentales, en particulier lors de l'examen ou de la refactorisation du code. Le framework d'analyse statique de Clang se charge des tâches laborieuses liées aux preuves de sécurité des threads.

Ajouter GUARDED_BY_CONTEXT() aux membres de données dans des 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. Ajouter des annotations à tous les membres de données qui ne sont pas thread-safe. Les annotations inutiles sont sûres, mais les annotations manquantes présentent un risque de concurrence des 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 la séquence avant de procéder. À mesure que le code est déplacé dans les refactorisations, Clang continue à 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);
}

Ajout de GUARDED_BY() aux membres de données dans les classes thread-safe qui utilisent des mutex.

Certaines classes dans Chrome doivent utiliser des verrouillages pour assurer 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 lors de 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 l'acquisition de verrous

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

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