Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Always start SDK on the main thread #3291

Merged
merged 47 commits into from
Oct 11, 2023

Conversation

brustolin
Copy link
Contributor

📜 Description

We always assume the SDK would be initialized in the main thread during app initialization and we design the SDK around this idea (although not documented). This change ensures the initialization of the SDK in the main thread which will avoid other issues like #3280

💡 Motivation and Context

closes #3280

💚 How did you test it?

Unit test

📝 Checklist

You have to check all boxes before merging:

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

@github-actions
Copy link

github-actions bot commented Sep 19, 2023

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1241.47 ms 1266.67 ms 25.21 ms
Size 22.85 KiB 408.85 KiB 386.00 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
6bc5ae5 1207.23 ms 1216.66 ms 9.43 ms
0d32275 1245.80 ms 1267.80 ms 22.00 ms
7bc3c0d 1261.16 ms 1278.38 ms 17.22 ms
9fa25c2 1211.88 ms 1228.36 ms 16.48 ms
df2986b 1227.45 ms 1244.35 ms 16.90 ms
32e64d1 6272.19 ms 6299.50 ms 27.31 ms
b6ba04e 1230.48 ms 1253.20 ms 22.72 ms
c78683b 1246.71 ms 1258.70 ms 11.99 ms
4f660b4 1225.44 ms 1230.18 ms 4.75 ms
c9724f9 1199.38 ms 1229.54 ms 30.16 ms

App size

Revision Plain With Sentry Diff
6bc5ae5 20.76 KiB 401.39 KiB 380.63 KiB
0d32275 22.84 KiB 403.14 KiB 380.29 KiB
7bc3c0d 20.76 KiB 427.36 KiB 406.59 KiB
9fa25c2 22.85 KiB 407.44 KiB 384.59 KiB
df2986b 22.85 KiB 406.89 KiB 384.04 KiB
32e64d1 20.76 KiB 433.18 KiB 412.42 KiB
b6ba04e 20.76 KiB 414.44 KiB 393.68 KiB
c78683b 20.76 KiB 435.24 KiB 414.48 KiB
4f660b4 22.85 KiB 408.84 KiB 385.99 KiB
c9724f9 20.76 KiB 427.66 KiB 406.90 KiB

Previous results on branch: fix/access-UISession-main-thread

Startup times

Revision Plain With Sentry Diff
b29b31d 1257.30 ms 1279.60 ms 22.30 ms
3f07d67 1254.96 ms 1256.14 ms 1.18 ms
349516b 1217.77 ms 1231.30 ms 13.53 ms
61894d3 1226.06 ms 1245.32 ms 19.26 ms
4dbdaed 1226.33 ms 1236.74 ms 10.41 ms
db894fd 1270.41 ms 1277.38 ms 6.97 ms
67551be 1237.31 ms 1244.28 ms 6.97 ms
896e7eb 1224.24 ms 1251.42 ms 27.18 ms
3eb83a8 1232.88 ms 1244.90 ms 12.02 ms
21f2b5a 1199.76 ms 1217.48 ms 17.72 ms

App size

Revision Plain With Sentry Diff
b29b31d 22.85 KiB 408.84 KiB 386.00 KiB
3f07d67 22.85 KiB 407.75 KiB 384.90 KiB
349516b 22.85 KiB 408.84 KiB 385.99 KiB
61894d3 22.85 KiB 408.92 KiB 386.07 KiB
4dbdaed 22.85 KiB 408.85 KiB 386.00 KiB
db894fd 22.85 KiB 408.85 KiB 386.00 KiB
67551be 22.85 KiB 408.94 KiB 386.09 KiB
896e7eb 22.85 KiB 408.84 KiB 385.99 KiB
3eb83a8 22.85 KiB 408.93 KiB 386.08 KiB
21f2b5a 22.85 KiB 407.79 KiB 384.94 KiB

Copy link
Member

@armcknight armcknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple questions/requests for this one

Sources/SentryCrash/Recording/Tools/SentryCrashObjCApple.h Outdated Show resolved Hide resolved
Tests/SentryTests/SentryOptionsTest.m Outdated Show resolved Hide resolved
SentryTestUtils/MainThreadTestIntegration.swift Outdated Show resolved Hide resolved
Sources/Sentry/SentrySDK.m Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Sep 20, 2023

Codecov Report

Merging #3291 (0c88c23) into main (ac614f1) will increase coverage by 0.039%.
The diff coverage is 97.826%.

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #3291       +/-   ##
=============================================
+ Coverage   89.269%   89.308%   +0.039%     
=============================================
  Files          501       501               
  Lines        54078     54258      +180     
  Branches     19203     19496      +293     
=============================================
+ Hits         48275     48457      +182     
+ Misses        4949      4946        -3     
- Partials       854       855        +1     
Files Coverage Δ
Sources/Sentry/SentryReachability.m 97.333% <100.000%> (+0.231%) ⬆️
Sources/Sentry/SentrySDK.m 89.655% <100.000%> (+0.089%) ⬆️
Sources/Sentry/SentryThreadWrapper.m 100.000% <100.000%> (ø)
...s/SentryTests/Networking/SentryReachabilityTests.m 100.000% <100.000%> (ø)
Tests/SentryTests/SentrySDKTests.swift 97.319% <92.857%> (-0.094%) ⬇️

... and 65 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ac614f1...0c88c23. Read the comment docs.

Comment on lines 162 to 163
[SentryDependencyContainer.sharedInstance.dispatchQueueWrapper
dispatchAsyncOnMainQueue:startSDK];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've seen another dispatch invocation ([SentryThreadWrapper onMainThread:]) in the other PR 🤔 I guess this one resolving SentryDependencyContainer.sharedInstance (which visits some sync lock again) should be dropped completely in favour of wrapping in the SentryThreadWrapper type, just so that something so simple as sync/async dispatch to Main thread doesn't have to touch multiple instances around the Sentry scope & be performed with a very clear call path. 👌

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for following along here, the more eyes the better 👀 I guess you're talking about this: https://github.com/getsentry/sentry-cocoa/pull/3295/files#diff-1c7b8db05183d8ca8e29ad4450733675d013a6b4065104f150d37d04017a36beR20

That will always immediately return, as it will either directly execute the logic on the main thread if it's called from that context, or will dispatch asynchronously to the main queue otherwise, so we shouldn't see lock contention. The only issue is that if SDK consumers initialize from a non-main context, they can potentially lose information for events that happen very early in their launch sequence, but that should hopefully be a calculated tradeoff for whomever does that. We are going to recommend initializing on the main thread in our docs to avoid that kind of thing.

We are also working to resolve the lock contention we're seeing in SentryDependencyContainer in a third PR: #3294

Does this all sound correct/acceptable to you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking again, just a note for the future: we should have -[SentryThreadWrapper onMainThread:] use the dispatch queue wrapper, and then use it here as well since it's the same logic. Doesn't have to be in this PR though, it might involve other code/test changes.

@armcknight
Copy link
Member

The new test is failing in only some runs, will need more attention.

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brustolin, what's missing to get this merged? I see that the test is commented out. Let's please fix that.

@brustolin
Copy link
Contributor Author

@brustolin, what's missing to get this merged? I see that the test is commented out. Let's please fix that.

CI, very flaky, Im investigating.

Comment on lines -112 to -114
for (id<SentryReachabilityObserver> observer in sentry_reachability_change_blocks.allKeys) {
[self removeObserver:observer];
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This make reachability flaky during tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this change be in an extra PR?

@brustolin
Copy link
Contributor Author

@philipphofmann I think this is ready for review!!

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

CHANGELOG.md Outdated Show resolved Hide resolved
SentryTestUtils/MainThreadTestIntegration.swift Outdated Show resolved Hide resolved
Comment on lines -112 to -114
for (id<SentryReachabilityObserver> observer in sentry_reachability_change_blocks.allKeys) {
[self removeObserver:observer];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this change be in an extra PR?

@philipphofmann philipphofmann changed the title fix: Start SDK only in the main thread fix: Always start SDK on the main thread Oct 11, 2023
// We have to call the init on the main thread synchronously to guarantee the SDK gets
// initialized. Otherwise, users would init the SDK, and calls directly after would have
// undefined behavior as the SDK might not be initialized yet.
[SentryThreadWrapper onMainThreadSync:^{
Copy link
Contributor Author

@brustolin brustolin Oct 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philipphofmann, the first idea was to make it sync. But @armcknight and me agreed that making it sync may lead to deadlocks as we had in #3277.

We are aware of undefined behaviour if the user chooses to start it in a background thread, but that would be a user choice. I believe, the best thing we can do here is to document this very well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also afraid that this might cause deadlocks. We should be fine with the tradeoff if someone inits the SDK on a background thread that it isn't ready immediately before running into a deadlock. I will add some docs.

@philipphofmann philipphofmann merged commit 2401cbd into main Oct 11, 2023
62 of 66 checks passed
@philipphofmann philipphofmann deleted the fix/access-UISession-main-thread branch October 11, 2023 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

UIWindow called from background thread
5 participants