Skip to content

Commit 191a6b7

Browse files
committed
Fix ABBA deadlock.
onNewDataMessage() is called as a callback from Fast-RTPS when there is new data. When that happens, some locks inside of Fast-RTPS are taken, followed by internalMutex_ in SubListener. However, the rest of SubListener takes internalMutex_ first, followed by calls into Fast-RTPS where locks are taken. This is an ABBA deadlock. Break the deadlock by doing the calls into Fast-RTPS before taking the internalMutex_. Signed-off-by: Chris Lalancette <[email protected]>
1 parent c8a0071 commit 191a6b7

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_subscriber_info.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,17 @@ class SubListener : public EventListenerInterface, public eprosima::fastrtps::Su
7878
void
7979
onNewDataMessage(eprosima::fastrtps::Subscriber * sub) final
8080
{
81+
// Make sure to call into Fast-RTPS before taking the lock to avoid an
82+
// ABBA deadlock between internalMutex_ and mutexes inside of Fast-RTPS.
83+
uint64_t unread_count = sub->getUnreadCount();
84+
8185
std::lock_guard<std::mutex> lock(internalMutex_);
8286

8387
// the change to liveliness_lost_count_ needs to be mutually exclusive with
8488
// rmw_wait() which checks hasEvent() and decides if wait() needs to be called
8589
ConditionalScopedLock clock(conditionMutex_, conditionVariable_);
8690

87-
data_.store(sub->getUnreadCount(), std::memory_order_relaxed);
91+
data_.store(unread_count, std::memory_order_relaxed);
8892
}
8993

9094
RMW_FASTRTPS_SHARED_CPP_PUBLIC
@@ -134,9 +138,13 @@ class SubListener : public EventListenerInterface, public eprosima::fastrtps::Su
134138
void
135139
data_taken(eprosima::fastrtps::Subscriber * sub)
136140
{
141+
// Make sure to call into Fast-RTPS before taking the lock to avoid an
142+
// ABBA deadlock between internalMutex_ and mutexes inside of Fast-RTPS.
143+
uint64_t unread_count = sub->getUnreadCount();
144+
137145
std::lock_guard<std::mutex> lock(internalMutex_);
138146
ConditionalScopedLock clock(conditionMutex_);
139-
data_.store(sub->getUnreadCount(), std::memory_order_relaxed);
147+
data_.store(unread_count, std::memory_order_relaxed);
140148
}
141149

142150
size_t publisherCount()

0 commit comments

Comments
 (0)