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

[SR-11055] swift_isUniquelyReferenced_nonNull_native crash #53447

Open
swift-ci opened this issue Jul 2, 2019 · 10 comments
Open

[SR-11055] swift_isUniquelyReferenced_nonNull_native crash #53447

swift-ci opened this issue Jul 2, 2019 · 10 comments

Comments

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Jul 2, 2019

Previous ID SR-11055
Radar None
Original Reporter trololo (JIRA User)
Type Bug

Attachment: Download

Environment

Version 10.2.1 (10E1001) and proper Swift version

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, RunTimeCrash
Assignee None
Priority Medium

md5: 6c4a8cf893466e923d1db63ba0a2eab8

Issue Description:

We recently published the application and found that the app crashes with such error

`swift_isUniquelyReferenced_nonNull_native`

We have got three different stacks with such bug

They are near the same

Thread 5 name:Thread 5 name:
Thread 5 Crashed:
0 libswiftCore.dylib 0x00000001cd27b7ec swift_isUniquelyReferenced_nonNull_native + 0 (SwiftObject.mm:1323)
1 <reducted> 0x00000001008bfd6c LegacyMechanic.append(for:legacyEngineFlow🙂 + 512 (LegacyMechanic.swift:0)
2 <reducted> 0x0000000100759764 closure #&#8203;1 in LegacyInitializationMechanic.execute(appModels:completionHandler🙂 + 1680 (LegacyInitializationMechanic.swift:103)
3 <reducted> 0x0000000100758eb0 LegacyInitializationMechanic.execute(appModels:completionHandler🙂 + 1088 (LegacyInitializationMechanic.swift:0)
4 <reducted> 0x000000010075a008 protocol witness for InitializationMechanic.execute(appModels:completionHandler🙂 in conformance ... + 20 (<compiler-generated>:0)
5 <reducted> 0x00000001007e0f70 specialized closure #&#8203;1 in InitializationBaseWorker.initializeEngine(appModels:completionHandler🙂 + 248 (InitializationBaseWorker.swift:37)
6 <reducted> 0x00000001006f3458 thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0)
7 libdispatch.dylib 0x000000019e920a38 _dispatch_call_block_and_release + 24 (init.c:1372)
8 libdispatch.dylib 0x000000019e9217d4 _dispatch_client_callout + 16 (object.m:511)
9 libdispatch.dylib 0x000000019e904afc _dispatch_root_queue_drain + 636 (inline_internal.h:2441)
10 libdispatch.dylib 0x000000019e905248 _dispatch_worker_thread2 + 116 (queue.c:6072)
11 libsystem_pthread.dylib 0x000000019eb011b4 _pthread_wqthread + 464 (pthread.c:2361)
12 libsystem_pthread.dylib 0x000000019eb03cd4 start_wqthread + 4
Thread 6:0 libsystem_pthread.dylib 0x000000019eb03cd0 start_wqthread + 0

@belkadan
Copy link
Contributor

@belkadan belkadan commented Jul 2, 2019

@mikeash, @Catfish-Man, any ideas where to start?

@mikeash
Copy link
Contributor

@mikeash mikeash commented Jul 2, 2019

Looks like LegacyMechanic.append is accessing a bad pointer, either a junk value or a pointer to an object that has already been destroyed. swift_isUniquelyReferenced_nonNull_native just accesses the refcount field and returns the appropriate value. I'd suggest looking for thread safety problems or other memory management trouble. trololo (JIRA User), if you'd like to post a full crash log, I may be able to give a bit more info.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jul 2, 2019

Comment by Vyacheslav (JIRA)

Ok . I’ll attach all crash logs asap

@mikeash
Copy link
Contributor

@mikeash mikeash commented Jul 2, 2019

Cool! I was about to edit my comment to say that it's even better if you can attach all of your crash logs, but you're clearly on top of it.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jul 2, 2019

Comment by Vyacheslav (JIRA)

Done.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jul 2, 2019

Comment by Vyacheslav (JIRA)

Btw, if you need more info, I will provide, of course .

@mikeash
Copy link
Contributor

@mikeash mikeash commented Jul 2, 2019

Thanks! This is interesting.

All three crashes are at the very first instruction of swift_isUniquelyReferenced_nonNull_native, which is ldr x8, [x0, #&#8203;0x8]. x0 contains the address of the object being checked. In all three crash logs, x0 contains the value 0x8000000000000000 which is clearly not anything like a valid object pointer.

I still think thread safety problems are the thing to look at. Something is overwriting an object pointer you're using, which could be due to your object being destroyed and another object allocated in its place. Two of the logs crashed while doing work inside LegacyInitializationMechanic.execute, and they also were running LegacyInitializationMechanic.execute on another thread at the same time. That location in LegacyInitializationMechanic.execute looks to be mutating a Dictionary. I'd bet it's mutating the same Dictionary on both threads without locking first. Similarly, the third log crashed in AppModelStorage.update while mutating a Set on two threads, and I'd bet that it's mutating the same Set on both threads without locking first.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jul 2, 2019

Comment by Vyacheslav (JIRA)

Ok. I have to read the code. I will write about your clues. Thanks!

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Jul 2, 2019

Comment by Vyacheslav (JIRA)

Ok. I've looked.

It seems you are right. But I don't actually understand why this code called twice at the same time.

LegacyInitializationMechanic contains dictionary inside.

As AppModelStorage, it seems you are right too. I'm removing and appending the object to the Set. The problem is that I currently don't understand why this method was called twice.

The most obvious solution is to wrap this code by serial operation queue. Am I right? Is it an expected behavior of a Collection?

@mikeash
Copy link
Contributor

@mikeash mikeash commented Jul 3, 2019

Yes, it's expected that concurrently mutating a collection on one thread while accessing it (either reading or mutating it) on another thread could result in a crash or unpredictable behavior.

A serial queue would be a great way to fix this. Set it up so that all accesses to any given collection happen on one serial queue and everything will work.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants