Skip to content

Commit 60f11fb

Browse files
authored
chore: dispatchAsyncOnMainQueue to dispatchAsyncOnMainQueueIfNotMainThread (#6132)
* fix: Always execute async even if called from main thread * Update changelog * Update changelog number * Rename old method to `dispatchAsyncOnMainQueueIfNotMainThread` to reflect the behavior * delete `DispatchAsyncOnMainQueue` * Fix tests
1 parent afaa522 commit 60f11fb

17 files changed

+113
-64
lines changed

SentryTestUtils/TestSentryDispatchQueueWrapper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import Foundation
3434
public var blockOnMainInvocations = Invocations<() -> Void>()
3535
public var blockBeforeMainBlock: () -> Bool = { true }
3636

37-
public override func dispatchAsyncOnMainQueue(block: @escaping () -> Void) {
37+
public override func dispatchAsyncOnMainQueueIfNotMainThread(block: @escaping () -> Void) {
3838
blockOnMainInvocations.record(block)
3939
if blockBeforeMainBlock() {
4040
block()

Sources/Sentry/Profiling/SentryContinuousProfiler.mm

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,19 @@ + (nullable SentryId *)currentProfilerID
197197
*/
198198
+ (void)scheduleTimer
199199
{
200-
sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{
201-
std::lock_guard<std::mutex> l(_threadUnsafe_gContinuousProfilerLock);
202-
if (_chunkTimer != nil) {
203-
SENTRY_LOG_WARN(@"There was already a timer in flight, but this codepath shouldn't be "
204-
@"taken if there is no profiler running.");
205-
return;
206-
}
207-
208-
_chunkTimer = sentry_scheduledTimerWithTarget(
209-
kSentryProfilerChunkExpirationInterval, self, @selector(timerExpired), nil, YES);
210-
});
200+
sentry_dispatchAsyncOnMainIfNotMainThread(
201+
SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{
202+
std::lock_guard<std::mutex> l(_threadUnsafe_gContinuousProfilerLock);
203+
if (_chunkTimer != nil) {
204+
SENTRY_LOG_WARN(
205+
@"There was already a timer in flight, but this codepath shouldn't be "
206+
@"taken if there is no profiler running.");
207+
return;
208+
}
209+
210+
_chunkTimer = sentry_scheduledTimerWithTarget(
211+
kSentryProfilerChunkExpirationInterval, self, @selector(timerExpired), nil, YES);
212+
});
211213
}
212214

213215
+ (void)timerExpired

Sources/Sentry/Profiling/SentryProfilerState.mm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ - (instancetype)init
7272
if (self = [super init]) {
7373
_mutableState = [[SentryProfilerMutableState alloc] init];
7474
_mainThreadID = 0;
75-
sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper,
75+
sentry_dispatchAsyncOnMainIfNotMainThread(
76+
SentryDependencyContainer.sharedInstance.dispatchQueueWrapper,
7677
^{ [self cacheMainThreadID]; });
7778
}
7879
return self;

Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@
105105
}
106106

107107
void
108-
sentry_dispatchAsyncOnMain(SentryDispatchQueueWrapper *wrapper, dispatch_block_t block)
108+
sentry_dispatchAsyncOnMainIfNotMainThread(
109+
SentryDispatchQueueWrapper *wrapper, dispatch_block_t block)
109110
{
110-
[wrapper dispatchAsyncOnMainQueue:block];
111+
[wrapper dispatchAsyncOnMainQueueIfNotMainThread:block];
111112
}
112113

113114
void

Sources/Sentry/Profiling/SentryTraceProfiler.mm

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ + (void)recordMetrics
8484
*/
8585
+ (void)scheduleTimeoutTimer
8686
{
87-
sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{
88-
std::lock_guard<std::mutex> l(_threadUnsafe_gTraceProfilerLock);
89-
if (_sentry_threadUnsafe_traceProfileTimeoutTimer != nil) {
90-
return;
91-
}
92-
93-
_sentry_threadUnsafe_traceProfileTimeoutTimer = sentry_scheduledTimer(
94-
kSentryProfilerTimeoutInterval, NO, ^{ [self timeoutTimerExpired]; });
95-
});
87+
sentry_dispatchAsyncOnMainIfNotMainThread(
88+
SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{
89+
std::lock_guard<std::mutex> l(_threadUnsafe_gTraceProfilerLock);
90+
if (_sentry_threadUnsafe_traceProfileTimeoutTimer != nil) {
91+
return;
92+
}
93+
94+
_sentry_threadUnsafe_traceProfileTimeoutTimer = sentry_scheduledTimer(
95+
kSentryProfilerTimeoutInterval, NO, ^{ [self timeoutTimerExpired]; });
96+
});
9697
}
9798

9899
+ (void)timeoutTimerExpired

Sources/Sentry/SentryANRTrackerV1.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ - (void)detectANRs
8787

8888
atomic_fetch_add_explicit(&ticksSinceUiUpdate, 1, memory_order_relaxed);
8989

90-
[self.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{
90+
[self.dispatchQueueWrapper dispatchAsyncOnMainQueueIfNotMainThread:^{
9191
atomic_store_explicit(&ticksSinceUiUpdate, 0, memory_order_relaxed);
9292

9393
bool isReported = atomic_load_explicit(&reported, memory_order_relaxed);

Sources/Sentry/SentryFramesTracker.m

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ - (void)resetProfilingTimestamps
113113
// The DisplayLink callback always runs on the main thread. We dispatch this to the main thread
114114
// instead to avoid using locks in the DisplayLink callback.
115115
[self.dispatchQueueWrapper
116-
dispatchAsyncOnMainQueue:^{ [self resetProfilingTimestampsInternal]; }];
116+
dispatchAsyncOnMainQueueIfNotMainThread:^{ [self resetProfilingTimestampsInternal]; }];
117117
}
118118

119119
- (void)resetProfilingTimestampsInternal
@@ -306,14 +306,15 @@ - (SentryFramesDelayResult *)getFramesDelay:(uint64_t)startSystemTimestamp
306306
- (void)addListener:(id<SentryFramesTrackerListener>)listener
307307
{
308308
// Adding listeners on the main thread to avoid race condition with new frame callback
309-
[self.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ [self.listeners addObject:listener]; }];
309+
[self.dispatchQueueWrapper
310+
dispatchAsyncOnMainQueueIfNotMainThread:^{ [self.listeners addObject:listener]; }];
310311
}
311312

312313
- (void)removeListener:(id<SentryFramesTrackerListener>)listener
313314
{
314315
// Removing listeners on the main thread to avoid race condition with new frame callback
315316
[self.dispatchQueueWrapper
316-
dispatchAsyncOnMainQueue:^{ [self.listeners removeObject:listener]; }];
317+
dispatchAsyncOnMainQueueIfNotMainThread:^{ [self.listeners removeObject:listener]; }];
317318
}
318319

319320
- (void)pause

Sources/Sentry/SentrySDKInternal.m

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -268,29 +268,30 @@ + (void)startWithOptions:(SentryOptions *)options
268268
= options.initialScope([[SentryScope alloc] initWithMaxBreadcrumbs:options.maxBreadcrumbs]);
269269

270270
SENTRY_LOG_DEBUG(@"Dispatching init work required to run on main thread.");
271-
[SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{
272-
SENTRY_LOG_DEBUG(@"SDK main thread init started...");
271+
[SentryDependencyContainer.sharedInstance.dispatchQueueWrapper
272+
dispatchAsyncOnMainQueueIfNotMainThread:^{
273+
SENTRY_LOG_DEBUG(@"SDK main thread init started...");
273274

274275
// The UIDeviceWrapper needs to start before the Hub, because the Hub
275276
// enriches the scope, which calls the UIDeviceWrapper.
276277
#if SENTRY_HAS_UIKIT
277-
[SentryDependencyContainer.sharedInstance.uiDeviceWrapper start];
278+
[SentryDependencyContainer.sharedInstance.uiDeviceWrapper start];
278279
#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT
279280

280-
// The Hub needs to be initialized with a client so that closing a session
281-
// can happen.
282-
SentryHub *hub = [[SentryHub alloc] initWithClient:newClient andScope:scope];
283-
[SentrySDKInternal setCurrentHub:hub];
281+
// The Hub needs to be initialized with a client so that closing a session
282+
// can happen.
283+
SentryHub *hub = [[SentryHub alloc] initWithClient:newClient andScope:scope];
284+
[SentrySDKInternal setCurrentHub:hub];
284285

285-
[SentryDependencyContainer.sharedInstance.crashWrapper startBinaryImageCache];
286-
[SentryDependencyContainer.sharedInstance.binaryImageCache start:options.debug];
286+
[SentryDependencyContainer.sharedInstance.crashWrapper startBinaryImageCache];
287+
[SentryDependencyContainer.sharedInstance.binaryImageCache start:options.debug];
287288

288-
[SentrySDKInternal installIntegrations];
289+
[SentrySDKInternal installIntegrations];
289290

290291
#if SENTRY_TARGET_PROFILING_SUPPORTED
291-
sentry_sdkInitProfilerTasks(options, hub);
292+
sentry_sdkInitProfilerTasks(options, hub);
292293
#endif // SENTRY_TARGET_PROFILING_SUPPORTED
293-
}];
294+
}];
294295

295296
SENTRY_LOG_DEBUG(@"SDK initialized! Version: %@", SentryMeta.versionString);
296297
}

Sources/Sentry/SentrySubClassFinder.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ - (void)actOnSubclassesOfViewControllerInImage:(NSString *)imageName block:(void
8888
}
8989

9090
free(classes);
91-
[self.dispatchQueue dispatchAsyncOnMainQueue:^{
91+
[self.dispatchQueue dispatchAsyncOnMainQueueIfNotMainThread:^{
9292
for (NSString *className in classesToSwizzle) {
9393
block(NSClassFromString(className));
9494
}

Sources/Sentry/SentryTimeToDisplayTracker.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ - (void)reportFullyDisplayed
134134
SENTRY_LOG_DEBUG(@"Reporting full display for %@", _name);
135135
// All other accesses to _fullyDisplayedReported run on the main thread.
136136
// To avoid using locks, we execute this on the main queue instead.
137-
[_dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ self->_fullyDisplayedReported = YES; }];
137+
[_dispatchQueueWrapper
138+
dispatchAsyncOnMainQueueIfNotMainThread:^{ self->_fullyDisplayedReported = YES; }];
138139
}
139140

140141
- (void)finishSpansIfNotFinished

0 commit comments

Comments
 (0)