Skip to content

Commit 8fbf603

Browse files
mralephCommit Queue
authored andcommitted
[tsan] Improve suppression for tzset
When running under TSAN disable inlining of LocalTime helper so we can write a suppression using its name. Fixes #61396 TEST=ci Cq-Include-Trybots: luci.dart.try:vm-tsan-linux-release-x64-try,vm-tsan-linux-release-arm64-try Change-Id: I9f07572b5b597343dbc61554c4f287eac630f047 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/446720 Commit-Queue: Slava Egorov <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 1a7e113 commit 8fbf603

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

build/sanitizers/sanitizer_options.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ SANITIZER_HOOK_ATTRIBUTE const char* __tsan_default_suppressions() {
2929
# In some environments tzset_internal is not symbolized correctly so we
3030
# also suppress the closest caller which is properly symbolized.
3131
race:tzset_internal
32-
race:dart::DN_HelperDateTime_timeZoneOffsetInSeconds
32+
race:dart::LocalTime
3333
)";
3434
}
3535
#endif // defined(USING_THREAD_SANITIZER) && defined(DART_HOST_OS_LINUX)

runtime/vm/os_linux.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,33 @@ intptr_t OS::ProcessId() {
415415
return static_cast<intptr_t>(getpid());
416416
}
417417

418+
// TSAN detects data races inside tzset implementation because it does not
419+
// understand low-level synchronization primitives used by libc. We would
420+
// like to suppress these false positives, however writing a suppression
421+
// targeting tzset is hard because
422+
//
423+
// 1. On our bots TSAN fails to properly symbolize
424+
// libc symbols (meaning that we can't simply suppress tzset itself).
425+
// 2. libc is compiled without frame-pointers so TzSet caller is missing
426+
// from the stack trace.
427+
//
428+
// To work-around both issues we create a simple wrapper over TzSet with is
429+
// not inlined to guarantee that LocalTime (the caller of this wrapper)
430+
// appears in the stack trace and we can suppress false positive occurring
431+
// inside it.
432+
#if defined(USING_THREAD_SANITIZER)
433+
DART_NOINLINE
434+
#else
435+
DART_FORCE_INLINE
436+
#endif
437+
static void TzSet() {
438+
tzset();
439+
}
440+
418441
static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) {
419442
time_t seconds = static_cast<time_t>(seconds_since_epoch);
420443
if (seconds != seconds_since_epoch) return false;
421-
tzset(); // Not guaranteed by POSIX to be called by `localtime_r`.
444+
TzSet(); // Not guaranteed by POSIX to be called by `localtime_r`.
422445
struct tm* error_code = localtime_r(&seconds, tm_result);
423446
return error_code != nullptr;
424447
}

0 commit comments

Comments
 (0)