I'm looking at https://bugs.swift.org/browse/SR-2879 
<https://bugs.swift.org/browse/SR-2879> which is exposing itself through an 
over-release of a constant CF string (in this case, kCFEmptyString). I don't 
believe it to be a Swift related problem, because Swift doesn't get into the 
internals of CFCalendar where the problem occurs.

The problem is that CFCalendar releases the localeID when it's deallocated:

if (calendar->_localeID) CFRelease(calendar->_localeID);

https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L54
 
<https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L54>
 

The problem is that when the localeID is assigned, it doesn't appear to be 
copied or renamed:

calendar->_localeID = CFLocaleGetIdentifier(CFLocaleGetSystem());

https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L252
 
<https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L252>
 
https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L281
 
<https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L281>
  

but elsewhere in the code, we do retain it:

   CFStringRef localeID = CFLocaleGetIdentifier(locale);
    if (localeID != calendar->_localeID) {
        CFRelease(calendar->_localeID);
        CFRetain(localeID);

https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L303-L306
 
<https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFCalendar.c#L303-L306>
 

When a locale isn't supplied, it uses the default global one, which is defined 
to be an empty string:

CFLocaleRef CFLocaleGetSystem(void) {
    CFLocaleRef locale;
    CFLocaleRef uselessLocale = NULL; //if we lose the race creating the global 
locale, we need to release the one we created, but we want to do it outside the 
lock.
    __CFLocaleLockGlobal();
    if (NULL == __CFLocaleSystem) {
        __CFLocaleUnlockGlobal();
        locale = CFLocaleCreate(kCFAllocatorSystemDefault, CFSTR(""));
        if (!locale) return NULL;

https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFLocale.c#L255-L261
 
<https://github.com/apple/swift-corelibs-foundation/blob/1a76e814212e781a9d50782ee24117760cfe9b48/CoreFoundation/Locale.subproj/CFLocale.c#L255-L261>
 

The CFSTR("") results in a reference to kCFEmptyString, which reduces by one 
each time a CFCalendar is created and destroyed, leading to the (unrelated) 
test failures of https://github.com/apple/swift-corelibs-foundation/pull/667 
<https://github.com/apple/swift-corelibs-foundation/pull/667> as documented in 
https://bugs.swift.org/browse/SR-2879 <https://bugs.swift.org/browse/SR-2879>

My suggestion is to insert a CFRetain when the calendar->locale is set, to 
balance out the CFRelease that's being performed in the deallocator. Building 
with this simple change and checking the retain count of kCFEmptyString 
verifies that it does fix the problem, although I'm open to suggestions as to 
improvements of where the retain takes place, if not on lines 252 and 282.

  1> import Foundation 
  2> :p (int)swift_retainCount(&__kCFEmptyString) 
(int) $11 = 1
  2> _ = Calendar(identifier:.gregorian)
  3> :p (int)swift_retainCount(&__kCFEmptyString) 
(int) $12 = 3
  3> _ = Calendar(identifier:.chinese)
  4> :p (int)swift_retainCount(&__kCFEmptyString) 
(int) $13 = 3
  4> _ = Calendar(identifier:.hebrew)
  5> :p (int)swift_retainCount(&__kCFEmptyString) 
(int) $14 = 3
  5> ^D

Alex
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

Reply via email to