Skip to content

Commit c5ea9e0

Browse files
committed
TSAN triggers false positives because TSAN does not mark EOWNERDEAD returning timed_lock as locked. Annotations can't help here, so a try-based alternative is tested when TSAN is active
1 parent 922be97 commit c5ea9e0

4 files changed

Lines changed: 37 additions & 7 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,8 @@ jobs:
699699
#TSAN options
700700
if [ -n "${{matrix.tsan}}" ]
701701
then
702-
export TSAN_OPTIONS="verbosity=1:print_stacktrace=1"
702+
#print_stacktrace is not a ThreadSanitizer option
703+
export TSAN_OPTIONS="verbosity=1"
703704
B2_ARGS+=("thread-sanitizer=norecover" "define=TSAN=1")
704705
fi
705706
#Common UBSAN / ASAN / TSAN options
@@ -939,7 +940,8 @@ jobs:
939940
#TSAN options
940941
if [ -n "${{matrix.tsan}}" ]
941942
then
942-
export TSAN_OPTIONS="verbosity=1:print_stacktrace=1"
943+
#print_stacktrace is not a ThreadSanitizer option
944+
export TSAN_OPTIONS="verbosity=1"
943945
B2_ARGS+=("thread-sanitizer=norecover" "define=TSAN=1")
944946
fi
945947
#Common UBSAN / ASAN / TSAN options
@@ -1136,7 +1138,8 @@ jobs:
11361138
#TSAN options
11371139
if [ -n "${{matrix.tsan}}" ]
11381140
then
1139-
export TSAN_OPTIONS="verbosity=1:print_stacktrace=1"
1141+
#print_stacktrace is not a ThreadSanitizer option
1142+
export TSAN_OPTIONS="verbosity=1"
11401143
B2_ARGS+=("thread-sanitizer=norecover" "define=TSAN=1")
11411144
fi
11421145
#Common UBSAN / ASAN / TSAN options

‎include/boost/interprocess/detail/workaround.hpp‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,33 @@
188188
# define BOOST_INTERPROCESS_MAPPED_FILES
189189
#endif
190190

191+
//////////////////////////////////////////////////////
192+
// BOOST_INTERPROCESS_THREAD_SANITIZER
193+
//////////////////////////////////////////////////////
194+
#if defined(__has_feature)
195+
#if __has_feature(thread_sanitizer)
196+
#define BOOST_INTERPROCESS_THREAD_SANITIZER
197+
#endif
198+
#endif
199+
#if !defined(BOOST_INTERPROCESS_THREAD_SANITIZER) && defined(__SANITIZE_THREAD__)
200+
#define BOOST_INTERPROCESS_THREAD_SANITIZER
201+
#endif
202+
203+
//////////////////////////////////////////////////////
204+
// BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND
205+
//////////////////////////////////////////////////////
206+
//ThreadSanitizer's pthread_mutex_lock and pthread_mutex_trylock interceptors
207+
//know that an EOWNERDEAD return from a robust mutex means the mutex *was*
208+
//acquired, but its pthread_mutex_timedlock interceptor does not. The mutex is
209+
//not registered as owned by the caller and the mandatory unlock that marks it
210+
//as unrecoverable is then reported as "unlock of an unlocked mutex". Emulate
211+
//the timed lock with try_lock while that limitation lasts.
212+
#if defined(BOOST_INTERPROCESS_THREAD_SANITIZER)
213+
#if defined(BOOST_INTERPROCESS_POSIX_TIMEOUTS) && defined(BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES)
214+
#define BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND
215+
#endif
216+
#endif
217+
191218
//Now declare some Boost.Interprocess features depending on the implementation
192219
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
193220
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES

‎include/boost/interprocess/sync/posix/mutex.hpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
#include <boost/interprocess/timed_utils.hpp>
4848

4949

50-
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
50+
#if !defined(BOOST_INTERPROCESS_POSIX_TIMEOUTS) || defined(BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND)
5151
# include <boost/interprocess/detail/os_thread_functions.hpp>
5252
# include <boost/interprocess/sync/detail/common_algorithms.hpp>
5353
#endif
@@ -141,7 +141,7 @@ inline bool posix_mutex::try_lock()
141141
template<class TimePoint>
142142
inline bool posix_mutex::timed_lock(const TimePoint &abs_time)
143143
{
144-
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
144+
#if defined(BOOST_INTERPROCESS_POSIX_TIMEOUTS) && !defined(BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND)
145145
//Posix does not support infinity absolute time so handle it here
146146
if(ipcdetail::is_pos_infinity(abs_time)){
147147
this->lock();

‎include/boost/interprocess/sync/posix/recursive_mutex.hpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
4545
#include <boost/interprocess/timed_utils.hpp>
4646
#include <boost/interprocess/exceptions.hpp>
47-
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
47+
#if !defined(BOOST_INTERPROCESS_POSIX_TIMEOUTS) || defined(BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND)
4848
# include <boost/interprocess/detail/os_thread_functions.hpp>
4949
# include <boost/interprocess/sync/detail/common_algorithms.hpp>
5050
#endif
@@ -127,7 +127,7 @@ inline bool posix_recursive_mutex::try_lock()
127127
template<class TimePoint>
128128
inline bool posix_recursive_mutex::timed_lock(const TimePoint &abs_time)
129129
{
130-
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
130+
#if defined(BOOST_INTERPROCESS_POSIX_TIMEOUTS) && !defined(BOOST_INTERPROCESS_TSAN_ROBUST_TIMEDLOCK_WORKAROUND)
131131
//Posix does not support infinity absolute time so handle it here
132132
if(ipcdetail::is_pos_infinity(abs_time)){
133133
this->lock();

0 commit comments

Comments
 (0)