Skip to content

Commit

Permalink
ref: Ignore more thread sanitizer warnings in code (#3923)
Browse files Browse the repository at this point in the history
Ignore the thread sanitizer in the code where possible, which has the
advantage of knowing a method is ignored when reading the code and not
jumping to the ThreadSanitizer.sup file. Furthermore, use the
ThreadSanitizer.sup file not only for tests but for the Run Xcode
schemes.
  • Loading branch information
philipphofmann authored Apr 30, 2024
1 parent e887ddc commit 265f000
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 53 deletions.
2 changes: 1 addition & 1 deletion Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,6 @@
isa = PBXGroup;
children = (
844DA7F6282435CD00E6B62E /* README.md */,
7B9660B12783500E0014A767 /* ThreadSanitizer.sup */,
630C01951EC341D600C52CEF /* Resources */,
63AA76AA1EB9D5CD00D153DE /* Configuration */,
63AA75931EB8AEDB00D153DE /* SentryTests */,
Expand Down Expand Up @@ -3728,6 +3727,7 @@
D8B0542F2A7D35F10056BAF6 /* Resources */ = {
isa = PBXGroup;
children = (
7B9660B12783500E0014A767 /* ThreadSanitizer.sup */,
D8B0542D2A7D2C720056BAF6 /* PrivacyInfo.xcprivacy */,
D8511F722BAC8F750015E6FD /* Sentry.modulemap */,
);
Expand Down
9 changes: 8 additions & 1 deletion Sentry.xcodeproj/xcshareddata/xcschemes/Sentry.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<EnvironmentVariables>
<EnvironmentVariable
key = "TSAN_OPTIONS"
value = "suppressions=$(PROJECT_DIR)/Tests/ThreadSanitizer.sup"
value = "suppressions=$(PROJECT_DIR)/Sources/Resources/ThreadSanitizer.sup"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
Expand Down Expand Up @@ -159,6 +159,13 @@
ReferencedContainer = "container:Sentry.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "TSAN_OPTIONS"
value = "suppressions=$(PROJECT_DIR)/Sources/Resources/ThreadSanitizer.sup"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
11 changes: 9 additions & 2 deletions SentryTestUtils/TestSentryDispatchQueueWrapper.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import _SentryPrivate
import Foundation
@testable import Sentry

/// A wrapper around `SentryDispatchQueueWrapper` that memoized invocations to its methods and allows customization of async logic, specifically: dispatch-after calls can be made to run immediately, or not at all.
public class TestSentryDispatchQueueWrapper: SentryDispatchQueueWrapper {

private let dispatchAsyncLock = NSLock()

public var dispatchAsyncCalled = 0

/// Whether or not delayed dispatches should execute.
Expand All @@ -13,8 +16,12 @@ public class TestSentryDispatchQueueWrapper: SentryDispatchQueueWrapper {
public var dispatchAsyncInvocations = Invocations<() -> Void>()
public var dispatchAsyncExecutesBlock = true
public override func dispatchAsync(_ block: @escaping () -> Void) {
dispatchAsyncCalled += 1
dispatchAsyncInvocations.record(block)

dispatchAsyncLock.synchronized {
dispatchAsyncCalled += 1
dispatchAsyncInvocations.record(block)
}

if dispatchAsyncExecutesBlock {
block()
}
Expand Down
11 changes: 11 additions & 0 deletions Sources/Resources/ThreadSanitizer.sup
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ThreadSanitizer suppressions file
# For syntax details, see https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions

# Races to fix
race:returnResponse
race:enableNetworkTracking
race:enableNetworkBreadcrumbs
race:disable
race:URLSessionDataTaskMock
race:getOriginalImplementation
race:SentrySpanContext
53 changes: 36 additions & 17 deletions Sources/Sentry/SentryDependencyContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#import "SentryDisplayLinkWrapper.h"
#import "SentryExtraContextProvider.h"
#import "SentryFileManager.h"
#import "SentryInternalCDefines.h"
#import "SentryLog.h"
#import "SentryNSProcessInfoWrapper.h"
#import "SentryNSTimerFactory.h"
Expand Down Expand Up @@ -120,7 +121,8 @@ - (SentryAppStateManager *)appStateManager
}
}

- (SentryCrashWrapper *)crashWrapper
- (SentryCrashWrapper *)crashWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_crashWrapper == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -132,7 +134,8 @@ - (SentryCrashWrapper *)crashWrapper
return _crashWrapper;
}

- (SentryCrash *)crashReporter
- (SentryCrash *)crashReporter SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_crashReporter == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -145,7 +148,8 @@ - (SentryCrash *)crashReporter
return _crashReporter;
}

- (SentrySysctl *)sysctlWrapper
- (SentrySysctl *)sysctlWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_sysctlWrapper == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -157,7 +161,8 @@ - (SentrySysctl *)sysctlWrapper
return _sysctlWrapper;
}

- (SentryThreadInspector *)threadInspector
- (SentryThreadInspector *)threadInspector SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_threadInspector == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -170,7 +175,8 @@ - (SentryThreadInspector *)threadInspector
return _threadInspector;
}

- (SentryExtraContextProvider *)extraContextProvider
- (SentryExtraContextProvider *)extraContextProvider SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_extraContextProvider == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -193,7 +199,8 @@ - (SentryNSNotificationCenterWrapper *)notificationCenterWrapper
}

#if TARGET_OS_IOS
- (SentryUIDeviceWrapper *)uiDeviceWrapper
- (SentryUIDeviceWrapper *)uiDeviceWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_uiDeviceWrapper == nil) {
Expand All @@ -214,7 +221,8 @@ - (SentryUIDeviceWrapper *)uiDeviceWrapper
#endif // TARGET_OS_IOS

#if SENTRY_UIKIT_AVAILABLE
- (SentryScreenshot *)screenshot
- (SentryScreenshot *)screenshot SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_screenshot == nil) {
Expand All @@ -233,7 +241,8 @@ - (SentryScreenshot *)screenshot
# endif // SENTRY_HAS_UIKIT
}

- (SentryViewHierarchy *)viewHierarchy
- (SentryViewHierarchy *)viewHierarchy SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_viewHierarchy == nil) {
Expand All @@ -252,7 +261,8 @@ - (SentryViewHierarchy *)viewHierarchy
# endif // SENTRY_HAS_UIKIT
}

- (SentryUIApplication *)application
- (SentryUIApplication *)application SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_application == nil) {
Expand All @@ -271,7 +281,8 @@ - (SentryUIApplication *)application
# endif // SENTRY_HAS_UIKIT
}

- (SentryFramesTracker *)framesTracker
- (SentryFramesTracker *)framesTracker SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_framesTracker == nil) {
Expand All @@ -294,7 +305,8 @@ - (SentryFramesTracker *)framesTracker
# endif // SENTRY_HAS_UIKIT
}

- (SentrySwizzleWrapper *)swizzleWrapper
- (SentrySwizzleWrapper *)swizzleWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
# if SENTRY_HAS_UIKIT
if (_swizzleWrapper == nil) {
Expand All @@ -315,6 +327,7 @@ - (SentrySwizzleWrapper *)swizzleWrapper
#endif // SENTRY_UIKIT_AVAILABLE

- (SentryANRTracker *)getANRTracker:(NSTimeInterval)timeout
SENTRY_DISABLE_THREAD_SANITIZER("double-checked lock produce false alarms")
{
if (_anrTracker == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -331,7 +344,8 @@ - (SentryANRTracker *)getANRTracker:(NSTimeInterval)timeout
return _anrTracker;
}

- (SentryNSProcessInfoWrapper *)processInfoWrapper
- (SentryNSProcessInfoWrapper *)processInfoWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_processInfoWrapper == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -343,7 +357,8 @@ - (SentryNSProcessInfoWrapper *)processInfoWrapper
return _processInfoWrapper;
}

- (SentrySystemWrapper *)systemWrapper
- (SentrySystemWrapper *)systemWrapper SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_systemWrapper == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -355,7 +370,8 @@ - (SentrySystemWrapper *)systemWrapper
return _systemWrapper;
}

- (SentryDispatchFactory *)dispatchFactory
- (SentryDispatchFactory *)dispatchFactory SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_dispatchFactory == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -367,7 +383,8 @@ - (SentryDispatchFactory *)dispatchFactory
return _dispatchFactory;
}

- (SentryNSTimerFactory *)timerFactory
- (SentryNSTimerFactory *)timerFactory SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_timerFactory == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -380,7 +397,8 @@ - (SentryNSTimerFactory *)timerFactory
}

#if SENTRY_HAS_METRIC_KIT
- (SentryMXManager *)metricKitManager
- (SentryMXManager *)metricKitManager SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_metricKitManager == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand All @@ -399,7 +417,8 @@ - (SentryMXManager *)metricKitManager
#endif // SENTRY_HAS_METRIC_KIT

#if SENTRY_HAS_REACHABILITY
- (SentryReachability *)reachability
- (SentryReachability *)reachability SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
if (_reachability == nil) {
@synchronized(sentryDependencyContainerLock) {
Expand Down
22 changes: 8 additions & 14 deletions Sources/Sentry/SentryFramesTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# import "SentryDelayedFramesTracker.h"
# import "SentryDispatchQueueWrapper.h"
# import "SentryDisplayLinkWrapper.h"
# import "SentryInternalDefines.h"
# import "SentryInternalCDefines.h"
# import "SentryLog.h"
# import "SentryProfiler+Private.h"
# import "SentryProfilingConditionals.h"
Expand Down Expand Up @@ -87,22 +87,16 @@ - (void)setDisplayLinkWrapper:(SentryDisplayLinkWrapper *)displayLinkWrapper
{
_displayLinkWrapper = displayLinkWrapper;
}

/**
* As you can only disable the thread sanitizer for methods, we must manually create the setter
* here.
*/
- (void)setPreviousFrameSystemTimestamp:(uint64_t)previousFrameSystemTimestamp
SENTRY_DISABLE_THREAD_SANITIZER
SENTRY_DISABLE_THREAD_SANITIZER("As you can only disable the thread sanitizer for methods, we "
"must manually create the setter here.")
{
_previousFrameSystemTimestamp = previousFrameSystemTimestamp;
}

/**
* As you can only disable the thread sanitizer for methods, we must manually create the getter
* here.
*/
- (uint64_t)getPreviousFrameSystemTimestamp SENTRY_DISABLE_THREAD_SANITIZER
- (uint64_t)getPreviousFrameSystemTimestamp SENTRY_DISABLE_THREAD_SANITIZER(
"As you can only disable the thread sanitizer for methods, we must manually create the getter "
"here.")
{
return _previousFrameSystemTimestamp;
}
Expand Down Expand Up @@ -251,7 +245,7 @@ - (void)recordTimestamp:(uint64_t)timestamp value:(NSNumber *)value array:(NSMut
}
# endif // SENTRY_TARGET_PROFILING_SUPPORTED

- (SentryScreenFrames *)currentFrames SENTRY_DISABLE_THREAD_SANITIZER
- (SentryScreenFrames *)currentFrames SENTRY_DISABLE_THREAD_SANITIZER()
{
# if SENTRY_TARGET_PROFILING_SUPPORTED
return [[SentryScreenFrames alloc] initWithTotal:_totalFrames
Expand All @@ -268,7 +262,7 @@ - (SentryScreenFrames *)currentFrames SENTRY_DISABLE_THREAD_SANITIZER
}

- (CFTimeInterval)getFramesDelay:(uint64_t)startSystemTimestamp
endSystemTimestamp:(uint64_t)endSystemTimestamp SENTRY_DISABLE_THREAD_SANITIZER
endSystemTimestamp:(uint64_t)endSystemTimestamp SENTRY_DISABLE_THREAD_SANITIZER()
{
return [self.delayedFramesTracker getFramesDelay:startSystemTimestamp
endSystemTimestamp:endSystemTimestamp
Expand Down
4 changes: 3 additions & 1 deletion Sources/Sentry/SentryTracer.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#import "SentryEvent+Private.h"
#import "SentryFileManager.h"
#import "SentryHub+Private.h"
#import "SentryInternalCDefines.h"
#import "SentryInternalDefines.h"
#import "SentryLog.h"
#import "SentryNSDictionarySanitize.h"
Expand Down Expand Up @@ -745,7 +746,8 @@ - (SentryTransaction *)toTransaction

#if SENTRY_HAS_UIKIT

- (nullable SentryAppStartMeasurement *)getAppStartMeasurement
- (nullable SentryAppStartMeasurement *)getAppStartMeasurement SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
{
// Only send app start measurement for transactions generated by auto performance
// instrumentation.
Expand Down
13 changes: 13 additions & 0 deletions Sources/Sentry/include/SentryInternalCDefines.h
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
typedef unsigned long long bytes;

/**
* For disabling the thread sanitizer for a method
*/
#if defined(__has_feature)
# if __has_feature(thread_sanitizer)
# define SENTRY_DISABLE_THREAD_SANITIZER(message) __attribute__((no_sanitize("thread")))
# else
# define SENTRY_DISABLE_THREAD_SANITIZER(message)
# endif
#else
# define SENTRY_DISABLE_THREAD_SANITIZER(message)
#endif
13 changes: 0 additions & 13 deletions Sources/Sentry/include/SentryInternalDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,3 @@ static NSString *const SentryPlatformName = @"cocoa";
#define SPAN_DATA_BLOCKED_MAIN_THREAD @"blocked_main_thread"
#define SPAN_DATA_THREAD_ID @"thread.id"
#define SPAN_DATA_THREAD_NAME @"thread.name"

/**
* For disabling the thread sanitizer for a method
*/
#if defined(__has_feature)
# if __has_feature(thread_sanitizer)
# define SENTRY_DISABLE_THREAD_SANITIZER __attribute__((no_sanitize("thread")))
# else
# define SENTRY_DISABLE_THREAD_SANITIZER
# endif
#else
# define SENTRY_DISABLE_THREAD_SANITIZER
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "SentryCrashStackCursor_MachineContext.h"
#include "SentryCrashSystemCapabilities.h"
#include "SentryCrashThread.h"
#include "SentryInternalCDefines.h"

// #define SentryCrashLogger_LocalLevel TRACE
#include "SentryCrashLogger.h"
Expand Down Expand Up @@ -409,7 +410,7 @@ handleExceptions(void *const userData)
// ============================================================================

static void
uninstallExceptionHandler(void)
uninstallExceptionHandler(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race to fix")
{
SentryCrashLOG_DEBUG("Uninstalling mach exception handler.");

Expand Down
Loading

0 comments on commit 265f000

Please sign in to comment.