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

XCode 9: Main Thread Checker: UI API called from background thread: -[UIApplication applicationIconBadgeNumber] must be called from main thread only #1146

Closed
mman opened this issue Jun 13, 2017 · 20 comments

Comments

@mman
Copy link
Contributor

mman commented Jun 13, 2017

Using the 1.14.4 version with XCode 9 on iOS 11 with the new main thread sanitizer activated.

This is the backtrace I got:

Main Thread Checker: UI API called on a background thread: -[UIApplication applicationIconBadgeNumber]
PID: 808, TID: 954593, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21
Backtrace:
4   PetMonitor                          0x0000000103fb5df4 -[PFApplication iconBadgeNumber] + 48
5   PetMonitor                          0x0000000103fb1164 -[PFInstallation _updateBadgeFromDevice] + 80
6   PetMonitor                          0x0000000103fb1020 -[PFInstallation _objectWillSave] + 96
7   PetMonitor                          0x0000000103f57728 __56-[PFObject(Private) _enqueueSaveEventuallyWithChildren:]_block_invoke.430 + 84
8   PetMonitor                          0x0000000103f27a00 __62-[BFTask continueWithExecutor:successBlock:cancellationToken:]_block_invoke + 92
9   PetMonitor                          0x0000000103f272a4 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 100
10  PetMonitor                          0x0000000103f285f8 __29+[BFExecutor defaultExecutor]_block_invoke_2 + 128
11  PetMonitor                          0x0000000103f28b58 -[BFExecutor execute:] + 76
12  PetMonitor                          0x0000000103f26e88 -[BFTask runContinuations] + 356
13  PetMonitor                          0x0000000103f26880 -[BFTask trySetResult:] + 152
14  PetMonitor                          0x0000000103f249cc -[BFTaskCompletionSource setResult:] + 80
15  PetMonitor                          0x0000000103f27580 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 300
16  PetMonitor                          0x0000000103f27364 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 292
17  libdispatch.dylib                   0x000000010685d654 _dispatch_call_block_and_release + 24
18  libdispatch.dylib                   0x000000010685d614 _dispatch_client_callout + 16
19  libdispatch.dylib                   0x0000000106869f00 _dispatch_queue_override_invoke + 1112
20  libdispatch.dylib                   0x000000010686fe4c _dispatch_root_queue_drain + 596
21  libdispatch.dylib                   0x000000010686fb98 _dispatch_worker_thread4 + 64
22  libsystem_pthread.dylib             0x00000001a8f71338 _pthread_wqthread + 1260
23  libsystem_pthread.dylib             0x00000001a8f70e40 start_wqthread + 4

Looks like PFApplication needs to dispatch back to the main queue to interact with UIApplication.

@flovilmart
Copy link
Contributor

Would you provide a Pr for that?

@mman
Copy link
Contributor Author

mman commented Jun 14, 2017

I'll try to get around to this during the summer, I'm currently bundling pre-built binaries of SDK so I'll need to spend some time to learn to rebuild the client side SDK code in order to test everything properly :). Are there any special steps needed to build? (read: I have not yet spent any minute investigating it :))

@loxx123
Copy link

loxx123 commented Jun 14, 2017

one quick thing to note here is that even before this new found issue using XCode 9 on iOS 11, Parse iOS/OSX SDK was spitting out anywhere from around 5-300 memory leaks per PFQuery, all pointing to BFTask and Save Eventually commands using Bolts. And no, these weren't my calls to save eventually or bolts, they were all internal issues to the SDK. The good thing was even though these issues were popping constantly, they never crashed the app or raised the memory load to a level exceeding ~50-100mb nor did i find that they forced retention of views or view controllers that accessed and used the Parse SDK. These were all issues of the same sort as listed above in the debug output, but we're game breakers. Most of these issues were only observable when running SDK without using Pods. I'll start linking these here as additional open issues here soon when I have time so the community can decide what to do here.

@flovilmart
Copy link
Contributor

For testing you can just use rake, (look into .travis.yaml) this should properly run the tests and ensure CI passes correctly.

@flovilmart
Copy link
Contributor

@larceneaux I've published a PR that addresses some memory leaks, can you have a look with the latest release?

@mman
Copy link
Contributor Author

mman commented Jul 26, 2017

I have prepared a PR against master, tested locally built framework against on one of my apps and main thread checker warnings are gone.

@funnel20
Copy link

funnel20 commented Sep 1, 2017

Is there any update on this?
I still see it with Parse 1.15.1, Xcode 9 beta 6 and iOS 11 beta 9

@flovilmart
Copy link
Contributor

flovilmart commented Sep 1, 2017

with making the call 'synchronized' on the main queue, the issue is that if you're 'waiting' on the main queue, your app will deadlock. (why @mman 's PR is failing at the moment). so we can't use a dispatch_sync technique to acquire this value.

@funnel20
Copy link

funnel20 commented Sep 4, 2017

Thank you for the update. I have shared a solution of another project in the PR: #1165
Hopefully that's helpful.

@claesjacobsson
Copy link

+1

1 similar comment
@alex-vasenin
Copy link

+1

@mman
Copy link
Contributor Author

mman commented Sep 7, 2017

Thinking about it a bit more. UIApplication.badgeCount emits a warning when not accessed from the main thread. I believe this is done via some special compiler annotation.

Since we are not accessing this property directly but via a wrapper PFApplication class, maybe a better approach would be to simply annotate PFApplication methods that invoke the appropriate UIApplication methods and fix the problem in places where PFApplication itself is invoked rather than enforcing this via dispatch_sync.

Thoughts?

@flovilmart
Copy link
Contributor

I like your approach, also, do we know if KVO works for UIApplication.badgeCount? That would be an elegant solution, prone to race conditions in extreme cases, but, acceptable

@claesjacobsson
Copy link

Anyone about to submit a PR regarding this?

@flovilmart
Copy link
Contributor

Submitted here: #1186

@claesjacobsson
Copy link

👍🏻 Thanks!

@flovilmart
Copy link
Contributor

This is still waiting for feedback, all tests are passing.

@funnel20
Copy link

I can confirm that this has been resolved in Parse 1.15.3 (which finally compiles thanks to the fix in #1159).
Verified with Xcode 9.0 and iOS 11.0.1.

This issue can be closed.

@claesjacobsson
Copy link

claesjacobsson commented Sep 27, 2017 via email

@flovilmart
Copy link
Contributor

Sweet!

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

No branches or pull requests

6 participants