Odcinek 25: Victor Costan w SFO (październik 2021 r.)
Poprzednie odcinki
W C++ możliwość prowadzenia wyścigów danych sprowadza się do niewielkiego dowodu prawidłowości w zakresie bezpieczeństwa wątków w przypadku każdego dostępu do danych. Te dowody są bardzo pracochłonne, zwłaszcza podczas przeglądania lub refaktoryzacji kodu. Statyczna platforma analizy Clang przejmuje całą ciężką pracę zabezpieczeń wątków.
Dodaj GUARDED_BY_CONTEXT()
do uczestników danych w klasach niezabezpieczonych wątkami
Większość klas Chrome jest niebezpieczna dla wątków 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, natomiast brak adnotacji zwiększa ryzyko ich generowania.
#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 sprawdzanie sekwencji
W zamian za dodawanie adnotacji do użytkowników Clang dba o to, aby każda metoda, która uzyskuje dostęp do danych, przeprowadziła kontrolę bezpieczeństwa sekwencji, zanim to zrobi. W trakcie refaktoryzacji kodu Clang kontynuuje egzekwowanie adnotacji 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);
}
Dodawanie GUARDED_BY()
do uczestników danych w klasach bezpiecznych dla wątków, które korzystają z 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 danych, które nie są bezpieczne w wątku. Każda adnotacja wskazuje muteks, który musi być zablokowany 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
Zaczekaj i pozwól kompilatorowi sprawdzić, czy każdy element base::AutoLock
ma prawidłowy zakres i że wywołania blokady Acquire()
i Release()
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);
}
- Wątki i Lista zadań w Chrome
- Analiza bezpieczeństwa wątków w Clang: poznaj inne adnotacje Clang w bardziej złożonych scenariuszach.