De Chromium Chronicle #25: Veiligheidsannotaties voor threads

Aflevering 25: door Victor Costan in SFO (oktober 2021)
Vorige afleveringen

In C++ komt het uitsluiten van de mogelijkheid van dataraces neer op een klein veiligheidsbewijs voor de correctheid van elke datalidtoegang. Deze bewijzen brengen veel mentale inspanning met zich mee, vooral bij het beoordelen of herstructureren van code. Het statische analyseraamwerk van Clang neemt het werk van de draadveiligheidsproeven over .

Voeg GUARDED_BY_CONTEXT() toe aan gegevensleden in thread-onveilige klassen

De meeste Chrome-klassen zijn thread-onveilig en moeten in één reeks worden gebruikt. Voeg annotaties toe aan alle gegevensleden die niet thread-safe zijn. Onnodige annotaties zijn veilig, maar ontbrekende annotaties vormen een risico op dataraces.

#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 dwingt volgordecontroles af

In ruil voor het annoteren van de gegevensleden zorgt Clang ervoor dat elke methode die toegang heeft tot de gegevens een veiligheidscontrole uitvoert voordat dit wordt gedaan. Terwijl code wordt verplaatst in refactorings, gaat Clang door met het afdwingen van de annotatie 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);
}

Voeg GUARDED_BY() toe aan gegevensleden in thread-safe klassen die mutexen gebruiken

Sommige klassen in Chrome moeten vergrendelingen gebruiken voor draadveiligheid. In deze gevallen annoteert u alle gegevensleden die niet thread-safe zijn. Elke annotatie verwijst naar een mutex die moet worden vastgehouden tijdens toegang tot het gegevenslid.

#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 dwingt de overname van sloten af

Wacht even en laat de compiler ervoor zorgen dat elke base::AutoLock de juiste scope heeft, en dat lock Acquire() en Release() aanroepen correct zijn gekoppeld.

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