The Chromium Chronicle #25: หมายเหตุเกี่ยวกับความปลอดภัยของเทรด

ตอนที่ 25: โดย Victor Costan ใน SFO (ตุลาคม 2021)
ตอนก่อนหน้า

ใน C++ การควบคุมความเป็นไปได้ของการแข่งขันด้านข้อมูลต้องอาศัยข้อพิสูจน์เล็กๆ น้อยๆ เกี่ยวกับความถูกต้องด้านความปลอดภัยของชุดข้อความสำหรับการเข้าถึงข้อมูลทุกรายการของสมาชิก การพิสูจน์เหล่านี้ก่อให้เกิดความยากลำบากทางจิตใจเป็นอย่างมาก โดยเฉพาะเมื่อตรวจสอบหรือเปลี่ยนโครงสร้างโค้ด เฟรมเวิร์กการวิเคราะห์แบบคงที่ของ Clang จะเข้ามาช่วยเรื่องการพิสูจน์ความปลอดภัยของชุดข้อความ

เพิ่ม GUARDED_BY_CONTEXT() ไปยังสมาชิกข้อมูลในชั้นเรียนที่ไม่ปลอดภัยของชุดข้อความ

คลาส Chrome ส่วนใหญ่ไม่ปลอดภัยต่อชุดข้อความและควรใช้ตามลำดับเดียว เพิ่มคำอธิบายประกอบให้กับสมาชิกข้อมูลทั้งหมดที่ไม่ปลอดภัยต่อชุดข้อความ คำอธิบายประกอบที่ไม่จำเป็นมีความปลอดภัย แต่คำอธิบายประกอบที่หายไปนั้นมีความเสี่ยงที่จะเกิดการแข่งขันด้านข้อมูล

#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 บังคับใช้การตรวจสอบลำดับ

แต่เพื่อเป็นการเขียนคำอธิบายประกอบให้กับสมาชิกข้อมูล Clang ช่วยให้มั่นใจว่าวิธีการใดก็ตามที่เข้าถึงข้อมูลจะทำการตรวจสอบความปลอดภัยของลำดับก่อนดำเนินการดังกล่าว เมื่อมีการย้ายโค้ดไปมาในการเปลี่ยนโครงสร้าง Clang ยังคงบังคับใช้คำอธิบายประกอบ 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);
}

เพิ่ม GUARDED_BY() ไปยังสมาชิกข้อมูลในชั้นเรียนที่ปลอดภัยของชุดข้อความที่ใช้ Mutex

บางคลาสใน Chrome ต้องใช้ล็อกเพื่อความปลอดภัยของชุดข้อความ ในกรณีเหล่านี้ ให้ใส่คำอธิบายประกอบสมาชิกข้อมูลทั้งหมดที่ไม่ปลอดภัยของชุดข้อความ คำอธิบายประกอบแต่ละรายการจะชี้ไปยัง hiddenx ที่ต้องระงับขณะเข้าถึงสมาชิกข้อมูล

#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 บังคับให้ล็อกการเข้าใหม่

พักสักครู่และให้คอมไพเลอร์ตรวจสอบว่า base::AutoLock แต่ละรายการมีการกำหนดขอบเขตอย่างถูกต้อง และล็อกการโทร Acquire() และ Release() นั้นจับคู่กันอย่างถูกต้อง

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