Skip to content

[Runtime] Change MetadataLookup section vectors to use ConcurrentReadableArray. #16753

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

Merged
merged 5 commits into from
May 23, 2018

Conversation

mikeash
Copy link
Contributor

@mikeash mikeash commented May 21, 2018

This fixes a deadlock that can occur when dyld loads new images into the process. MetadataLookup.cpp takes a lock to iterate over sections and while the lock is held it can call code which eventually calls _dyld_register_func_for_add_image which takes a lock inside dyld. Elsewhere, a function registered with _dyld_register_func_for_add_image gets called with that same dyld lock held, and tries to acquire the same lock in MetadataLookup.cpp. This inconsistent lock ordering results in a deadlock when the stars align just so.

The fix here is to switch to ConcurrentReadableArray which does not take a lock for reading. It still takes a lock for writing, but since that's only one half of the deadlock, that's OK.

Relevant stack trace excerpts for the curious:

1000  void (anonymous namespace)::addImageCallback<&((anonymous namespace)::TypeFieldRecordSection), &(swift::addImageTypeFieldDescriptorBlockCallback(void const*, unsigned long))>(mach_header const*, long) + 48 (libswiftCore.dylib + 3658928) [0x110ff34b0]
  1000  swift::addImageTypeFieldDescriptorBlockCallback(void const*, unsigned long) + 38 (libswiftCore.dylib + 3720902) [0x1110026c6]
    1000  swift::MutexPlatformHelper::lock(_opaque_pthread_mutex_t&) + 11 (libswiftCore.dylib + 3738827) [0x111006ccb]

1000  swift_getFieldAt + 685 (libswiftCore.dylib + 3723501) [0x1110030ed]
  1000  swift_getFieldAt::$_3::operator()(swift::reflection::FieldDescriptor const&) const + 237 (libswiftCore.dylib + 3724429) [0x11100348d]
    1000  swift_getFieldAt::$_2::operator()(swift::reflection::FieldDescriptor const&) const + 411 (libswiftCore.dylib + 3724075) [0x11100332b]
      1000  swift::_getTypeByMangledName(llvm::StringRef, llvm::function_ref<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>) + 659 (libswiftCore.dylib + 3722195) [0x111002bd3]
        1000  swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 112 (libswiftCore.dylib + 3726800) [0x111003dd0]
          1000  swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 207 (libswiftCore.dylib + 3726895) [0x111003e2f]
            1000  swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledNominalType(swift::Demangle::Node* const&, (anonymous namespace)::DecodedMetadataBuilder::BuiltNominalTypeDecl&, swift::TargetMetadata<swift::InProcess> const*&) + 1873 (libswiftCore.dylib + 3732193) [0x1110052e1]
              1000  dispatch_once_f + 41 (libdispatch.dylib + 5419) [0x7fff660e552b]
                1000  _dispatch_client_callout + 8 (libdispatch.dylib + 5490) [0x7fff660e5572]
                  1000  _dyld_register_func_for_add_image + 44 (libdyld.dylib + 19614) [0x7fff66123c9e]

rdar://problem/40230581

mikeash added 2 commits May 21, 2018 12:30
…apshots rather than using a callback-based read call.

rdar://problem/40230581
…urrentReadableArray rather than std::vector. This avoids the need to hold a lock while iterating, removing potential deadlocks.

rdar://problem/40230581
@mikeash mikeash requested review from DougGregor and jckarter May 21, 2018 16:53
@jckarter
Copy link
Contributor

Awesome, thanks for catching and fixing this!

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

Thank you! For some reason I didn't even stop to think that Mutex might not be reentrant but instead just blindly used the same pattern found in other places in this file while working on swift_getFieldAt :(

@mikeash
Copy link
Contributor Author

mikeash commented May 21, 2018

@xedin I don't think it would have occurred to me that _dyld_register_func_for_add_image would take a lock that would also be taken when invoking the callbacks, had I not seen it directly in the stack trace, so I certainly can't blame you for missing this.

@mikeash
Copy link
Contributor Author

mikeash commented May 21, 2018

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - b3d1030

@mikeash
Copy link
Contributor Author

mikeash commented May 22, 2018

@swift-ci Please test OS X platform

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - b3d1030

mikeash added 3 commits May 23, 2018 11:19
…apshots rather than using a callback-based read call.

rdar://problem/40230581
…ouble-free items. Also implement a destructor so it can be used for non-globals.

rdar://problem/40484362
@mikeash
Copy link
Contributor Author

mikeash commented May 23, 2018

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - b3d1030

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - b3d1030

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.

4 participants