-
Couldn't load subscription status.
- Fork 15k
Closed
Labels
libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Description
After #117497, using std::lock to acquire a mutex (i.e. not calling .lock() on the mutex itself) appears to not register that it acquires a lock, which can lead to erroneous thread safety warnings later that it needs to be held.
Live example: https://godbolt.org/z/vTrfK1f1r
void func() {
std::mutex a, b;
std::lock(a, b);
// error: calling function 'lock_guard' requires holding mutex 'a' exclusively [-Werror,-Wthread-safety-analysis]
std::lock_guard<std::mutex> a_guard(a, std::adopt_lock);
// error: calling function 'lock_guard' requires holding mutex 'b' exclusively [-Werror,-Wthread-safety-analysis]
std::lock_guard<std::mutex> b_guard(b, std::adopt_lock);
}Real example in LLDB:
llvm-project/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
Lines 180 to 185 in 6c072c0
| if (this != &rhs) { | |
| std::lock(m_collection_mutex, rhs.m_collection_mutex); | |
| std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock); | |
| std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock); | |
| m_break_loc_collection = rhs.m_break_loc_collection; | |
| } |
Also, use of this pattern when needing to acquire more than one lock is suggested at https://en.cppreference.com/w/cpp/thread/lock.html#Example
Here's a suggested fix that works for the breakages I've seen:
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -351,7 +351,7 @@
# endif // _LIBCPP_CXX03_LANG
template <class _L0, class _L1>
-_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
+_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1) {
while (true) {
{
unique_lock<_L0> __u0(__l0);Metadata
Metadata
Assignees
Labels
libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.