Guard against racy access to NSError.setUserInfoValueProvider. (#4280)

This API is documented in its headers to only allow being called once
for a particular domain, so we have to make sure our check for an
existing provider is synchronized with the setting.

rdar://problem/27541751
This commit is contained in:
Jordan Rose
2016-08-15 13:34:30 -07:00
committed by GitHub
parent 67008ae703
commit af1a8154a3
2 changed files with 5 additions and 2 deletions

View File

@@ -136,6 +136,9 @@ public extension Error {
}
}
internal let _errorDomainUserInfoProviderQueue = DispatchQueue(
label: "SwiftFoundation._errorDomainUserInfoProviderQueue")
/// Retrieve the default userInfo dictionary for a given error.
@_silgen_name("swift_Foundation_getErrorDefaultUserInfo")
public func _swift_Foundation_getErrorDefaultUserInfo(_ error: Error)
@@ -149,7 +152,8 @@ public func _swift_Foundation_getErrorDefaultUserInfo(_ error: Error)
// user-info value providers.
let domain = error._domain
if domain != NSCocoaErrorDomain {
if NSError.userInfoValueProvider(forDomain: domain) == nil {
_errorDomainUserInfoProviderQueue.sync {
if NSError.userInfoValueProvider(forDomain: domain) != nil { return }
NSError.setUserInfoValueProvider(forDomain: domain) { (nsError, key) in
let error = nsError as Error