Khả năng có lỗi của std::shared_mutex trên Windows
- Một nhóm phần mềm đã phát hiện hành vi bất ngờ liên quan đến
std::shared_mutex trên Windows.
- Vấn đề này chỉ xảy ra với MSVC, không xuất hiện trên MinGW hay các nền tảng khác.
- Khi luồng chính giành được khóa độc quyền rồi nhiều luồng con cố giành khóa chia sẻ, cứ khoảng 1 trên 1000 lần sẽ xảy ra "deadlock".
- Khi deadlock xảy ra, chỉ đúng 1 luồng con giành được khóa chia sẻ thành công, còn các luồng con khác bị chặn vĩnh viễn tại
lock_shared().
- Vấn đề này được quan sát thấy khi dùng
std::shared_mutex, std::shared_lock/std::unique_lock hoặc khi gọi trực tiếp các hàm SRW.
Ví dụ mã và tái hiện lỗi
- Có cung cấp đoạn mã đơn giản có thể tái hiện vấn đề.
- Đoạn mã lặp lại quá trình trong đó luồng chính giành khóa độc quyền, nhiều luồng con giành khóa chia sẻ rồi giải phóng nó.
- Đoạn mã này chỉ cho thấy lỗi liên quan đến
std::shared_mutex trên triển khai Windows MSVC.
Ý kiến của chuyên gia
- Nhà phát triển STL cho biết vấn đề này có vẻ là lỗi của Windows API.
- Đã có thảo luận về các bước phù hợp để báo cáo lỗi, và nhà phát triển STL đã báo cáo lỗi này nội bộ.
- Những người dùng khác đã điều tra chi tiết vấn đề và góp phần thu hẹp nguyên nhân xuống một lỗi cụ thể trong triển khai SRWLock.
Ý kiến của GN⁺
- Bài viết này cung cấp thông tin đặc biệt quan trọng với các lập trình viên C++, vì lỗi tiềm ẩn trong
std::shared_mutex có thể ảnh hưởng đến cơ chế đồng bộ hóa của các ứng dụng đa luồng.
- Nếu lỗi được xác nhận, điều này có thể ảnh hưởng đến mức độ tin cậy đối với triển khai của thư viện chuẩn C++. Các lập trình viên cần nhận thức được vấn đề này và có thể phải cân nhắc các cơ chế đồng bộ hóa thay thế.
- Vấn đề này có thể đặc biệt quan trọng trong các hệ thống hiệu năng cao hoặc thời gian thực, nơi deadlock có thể gây ra hậu quả nghiêm trọng.
- Trước khi áp dụng công nghệ này, các lập trình viên nên thực hiện kiểm thử rộng rãi trên nền tảng và trình biên dịch liên quan để xác nhận rằng không có kiểu lỗi như vậy.
- Để xử lý những vấn đề như thế này, các lập trình viên có thể cân nhắc các thư viện đồng bộ hóa thay thế như Boost. Vì Boost đã được kiểm thử rộng rãi và được sử dụng trên nhiều nền tảng, nó có thể cung cấp một phương án thay thế ổn định cho các vấn đề kiểu này.
1 bình luận
Ý kiến trên Hacker News
Một người dùng thắc mắc vì sao một vấn đề cơ bản như vậy lại không bị phát hiện trong thời gian dài và nhắc đến câu trả lời thuyết phục mà người khác đã đưa ra. Họ chỉ ra rằng có trường hợp một luồng đang cố lấy khóa ở chế độ chia sẻ lại vô tình giành được khóa ở chế độ độc quyền. Điều này xảy ra do sự chồng lấp của phép toán kiểm tra và thiết lập bit nguyên tử khi luồng lấy khóa chia sẻ và luồng nhả khóa độc quyền chạy đồng thời.
Một người dùng khác nói rằng họ không ngạc nhiên trước những bug tinh vi xuất hiện trong khóa Reader/Writer, đồng thời chia sẻ kinh nghiệm từng làm phần hiện thực nội bộ dựa trên Win32 trước thời kỳ C++11 và
std::shared_mutex. Vì có trải nghiệm tệ với khóa chia sẻ, họ cho biết sẽ tránh dùng chúng trừ khi thật sự cần thiết.Một người dùng chỉ ra rằng tiêu đề gây hiểu nhầm, và bug thực tế nằm ở khóa slim reader/writer (SRW) của Windows API; nó được phát hiện vì
std::shared_mutexđược hiện thực bằng khóa SRW. Một nhân viên Microsoft xác nhận rằng bug này đã được chuyển nội bộ tới nhóm Windows API.Một người dùng thắc mắc liệu cùng vấn đề này có xảy ra trong phần hiện thực của WINE hay không, và nói rằng họ cũng muốn thử trên bản cài XP tùy biến của mình. Trên bản cài đó, họ đã thêm nhiều phần mở rộng, bao gồm SRW API, và đã vá kernel để sửa một race condition gây deadlock trong keyed event API vốn dựa trên phần hiện thực SRW.
Có ý kiến chỉ ra rằng chương trình có bug. Nó trộn lẫn biến non-atomic và biến atomic để dùng trong vòng lặp kiểm tra
yield(), trong khi biến non-atomic không đảm bảo tính nhất quán bộ nhớ đệm giữa các luồng. Điều này có thể khiến vòng lặp chạy mãi mãi.Một người dùng nói rằng bug này có từ tận phiên bản Vista năm 2008 và bày tỏ sự ngạc nhiên khi suốt thời gian dài như vậy không ai phát hiện ra. Họ nhắc rằng trong cách dùng rwlock thông thường, có thể xuất hiện các trường hợp ngẫu nhiên không lấy được khóa chia sẻ, nhưng không dẫn đến deadlock.
Một người dùng nói rằng việc báo bug cho Windows API là cực kỳ khó, và dù họ được hướng dẫn báo qua Feedback Hub, cách đó hầu như không hiệu quả. Người này cho biết đã báo một bug trong đó
SRWLOCKcó thể rơi vào deadlock khi nhiều luồng đọc cố gắng cùng lúc giành quyền sở hữu chia sẻ sau khi chủ sở hữu độc quyền đã nhả quyền sở hữu.Một người dùng hồi tưởng rằng trước đây khi mua sản phẩm MS, họ có thể nhận được một support incident, và nếu phát hiện ra bug thật thì support incident đó sẽ được hoàn tiền. Họ nói đây là một hệ thống tốt, vừa hữu ích cho lập trình viên vừa giúp MS nhận được phản hồi để phát hiện vấn đề thực tế và cải thiện tài liệu. Họ tự hỏi liệu chương trình này còn tồn tại hay không.
Cuối cùng, một người dùng bày tỏ sự thất vọng trước việc báo bug cho Windows API quá khó khăn.