Re: CoreFoundation object over-retained during finalization
Re: CoreFoundation object over-retained during finalization
- Subject: Re: CoreFoundation object over-retained during finalization
- From: "email@hidden" <email@hidden>
- Date: Sat, 12 Mar 2011 19:41:11 +0000
On 12 Mar 2011, at 17:52, Quincey Morris wrote:
> On Mar 12, 2011, at 06:36, email@hidden wrote:
>
>> keychainRef also has an initial retainCount of 2 (the framework recycles the same object I presume).
>
> Unfortunately, this is meaningless. Trying to interpret retain count values leads to madness.
>
>> Either way I could not trigger an auto_zone_resurrection_error().
>
> Sorry, I ignored this key point -- where the error was detected. Although the error message didn't say this, the fact that is was reported as a resurrection error tells you one important thing -- the object had no strong references, but during the 'finalize' method of some other object your SecKeychainRef was CFRetain'ed again. Let's look at the crash report again:
>
>> Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
>> Exception Codes: 0x0000000000000001, 0x0000000000000000
>> Crashed Thread: 2 Dispatch queue: Garbage Collection Work Queue
>>
>> Application Specific Information:
>> objc[4128]: garbage collection is ON
>> fatal resurrection error for garbage block 0x10bbcf0(SecKeychain[304]): over-retained during finalization, refcount = 1
>> ...
>> malloc: garbage block 0x10bbcf0(SecKeychain[304]) was over-retained during finalization, refcount = 1
>> This could be an unbalanced CFRetain(), or CFRetain() balanced with -release.
>> Break on auto_zone_resurrection_error() to debug.
>> KosmicTask(4128,0xb013d000) malloc: fatal resurrection error for garbage block 0x10bbcf0(SecKeychain[304]): over-retained during finalization, refcount = 1
>
>
> So here's the sequence of events (I'm guessing):
>
> 1. The SecKeychainRef's lifetime had ended -- no strong references, no outstanding CFRetain.
>
> 2. Something called 'malloc' to allocate memory in the GC zone.
>
> 3. The collector decided to run during the 'malloc' call (maybe there wasn't enough free memory, or maybe it happened for kinky GC reasons).
>
> 4. The GC found all the dying objects, which included the SecKeychainRef and some others.
>
> 5. The GC started invoking 'finalize' on the dying objects.
>
> 6. Some object (most likely not the SecKeychainRef) CFRetain'ed the SecKeychainRef object. (It's not clear that this is technically illegal, but it seems like a bad idea. Leaving a finalize having left behind a new strong reference to a dying object is certainly illegal.) There was no balancing CFRelease.
>
> 7. It's interesting that the final crash was an illegal instruction. I'm not sure if that can be interpreted to mean that a function in one of the dead objects was called.
>
> So it's not simply a missing CFRelease during the normal flow of execution. There are at least two possibilities:
>
> 1. One of your 'finalize' methods invokes other methods that eventually cause something to retain the SecKeychainRef again. That sort of thing often happens when you do too much stuff in 'finalize', because you can inadvertently trigger consequences you never thought of. It's also possible that it's a frameworks 'finalize' that's doing it, not you, but that's probably not the best assumption to start from.
>
> 2. One of your 'finalize' methods does something that seems self-contained, but starts something asynchronous behind the scenes. Eventually, if this wasn't started from 'finalize', it would complete and the memory management would be balanced, but in this context it never gets to complete before the rug is pulled out.
>
> So, I'd try this two-headed approach:
>
> 1. Examine your code to try to find everything that could cause your SecKeychainRef to be retained (directly or indirectly, unfortunately), and try to figure out if this could be executed (directly or indirectly) during some 'finalize' or other.
>
> 2. Examine all your 'finalize' methods, and see if they could cause a SecKeychainRef to be retained (directly or indirectly), even if it's apparently only temporary and properly balanced by a CFRelease.
>
> Sorry, can't think of anything more useful than that.
>
Thanks again Quincey for the suggestions.
I have examined my code carefully and just cannot get any traction on this.
The SecKeychainRef is stashed on the stack and passed into a class method so I don't see how it could get anywhere near a finalize method.
I have encountered, and fixed, NSObject resurrection errors before but there was repeatability.
Maybe the finalize reference in the crash report is misleading - search for handle_overretained_garbage in the link below:
http://www.opensource.apple.com/source/libauto/libauto-141.2/AutoZone.cpp?txt
Does the finalize concept even apply in the context of a CFType?
I do utilise some other keychain access code but it doesn't create an explicit SecKeychainRef - though I presume the framework would have to.
I think I will have to wait on some more crash reports.
Thanks again.
Regards
Jonathan Mitchell
Developer
Mugginsoft LLP
http://www.mugginsoft.com
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden