Odcinek 25: Victor Costan w filmie SFO (październik 2021 r.)
Poprzednie odcinki
W C++ eliminacja możliwości wyścigu danych sprowadza się do małego dowodu poprawności zabezpieczeń wątków w przypadku każdego dostępu użytkownika do danych. Te dowody są źródłem wielu problemów psychicznych, zwłaszcza podczas sprawdzania lub refaktoryzacji kodu. Platforma Clang do analizy statycznej ułatwia pracę nad mechanizmami potwierdzenia bezpieczeństwa wątków.
Dodaj GUARDED_BY_CONTEXT()
do użytkowników danych w klasach niezabezpieczonych w wątkach
Większość klas Chrome nie jest zabezpieczona w wątkach i powinna być używana w jednej sekwencji. Dodaj adnotacje do wszystkich elementów danych, które nie są bezpieczne w wątkach. Zbędne adnotacje są bezpieczne, ale ich brak wiąże się z ryzykiem wyścigu danych.
#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 wymusza kontrole sekwencji
W zamian za dodanie adnotacji do użytkowników danych
Dzięki Clang każda metoda, która uzyskuje dostęp do danych, przeprowadza kontrolę zabezpieczeń sekwencji, zanim to zrobisz.
Podczas refaktoryzacji kodu
Clang nadal egzekwuje adnotację 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);
}
Dodaj GUARDED_BY()
do użytkowników danych w klasach bezpiecznych w wątkach, które używają muteksów.
Niektóre zajęcia w Chrome muszą używać blokad ze względu na bezpieczeństwo wątków. W takich przypadkach dodaj adnotacje do wszystkich użytkowników danych, którzy nie są dostępni w wątkach. Każda adnotacja wskazuje na muteks, który musi być przytrzymywany podczas uzyskiwania dostępu do użytkownika danych.
#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 wymusza pozyskanie blokady
Poczekaj i pozwól kompilatorowi upewnić się, że każde pole base::AutoLock
ma prawidłowy zakres.
a połączenia Acquire()
i Release()
z blokadą są prawidłowo sparowane.
void ThreadSafeCache::Set(base::StringPiece key, base::StringPiece value) {
base::AutoLock auto_lock(lock_); // Clang warns without this.
data_.emplace(key, value);
}
- Podział na wątki i Lista zadań w Chrome
- Analiza bezpieczeństwa wątków w Clang: więcej informacji o innych adnotacjach Clang na potrzeby bardziej złożonych scenariuszy.