Re: NSDocument, NSManagedObjectContext do Stuff in -dealloc, Cause Crash
Re: NSDocument, NSManagedObjectContext do Stuff in -dealloc, Cause Crash
- Subject: Re: NSDocument, NSManagedObjectContext do Stuff in -dealloc, Cause Crash
- From: "Paul Sanders" <email@hidden>
- Date: Thu, 31 Dec 2009 18:13:17 -0000
I can't comment on the specifics of this because I am not
knowledgable in that area, but the fact the undo manager is
getting it's knickers in a twist is surely unrelated to the fact
_releaseUndoManager was called from [NSDocument dealloc]. I do
all sorts of things in dealloc methods. I just try not to write
buggy code!
I have found that there is a more subtle problem that can arise
though. You're never quite sure when a dealloc method might be
called, especially with the way autorelease pools work, and that
occasionally means that resources you would like to release
*right now* hang around longer than you would like them to. I
therefore sometimes have a destroy method that I can call any
time I like. This releases (in the most general sense) anything
the object owns that are regarded as critical and leaves the
object in, effectively, a dormant state. Then, when dealloc is
finally called, the object quietly goes away. I don't have to
do this very often. Just for the occasional special case.
Of course, there's nothing to stop you temporarily retaining an
object in a dealloc method if you need it to stay around while
you do whatever cleanup you need to do. Just releae it at the
end of the method.
Paul Sanders.
----- Original Message -----
From: "Jerry Krinock" <email@hidden>
To: "Cocoa Developers" <email@hidden>
Sent: Thursday, December 31, 2009 5:36 PM
Subject: NSDocument, NSManagedObjectContext do Stuff
in -dealloc, Cause Crash
I remember reading that the only safe thing to do in your
dealloc method is to release instance variables. If you look at
lines #23 - #25 in the call stack below, it appears that
NSDocument's -dealloc is doing more, sending -removeAllActions
to its undo manager. Similarly, lines #7 and #8 say that
NSManagedObjectContext's -dealloc is removing tasks which target
itself from its undo manager.
Now I must admit that I have often found it difficult to find a
place other than -dealloc to remove observations and
dependencies like this, and have gotten away with it on
occasion. In this case, however, it seems to result in a crash
upon closing a Core Data document with unsaved changes (whether
saving or not), when using a custom undo manager.
Here is how I see the steps in the crash:
* During its -dealloc, NSDocument sends itself
_releaseUndoManager, which sends -removeAllActions to the
document's undo manager.
* The undo manager sends -removeAllObjects to its undo stack.
* The first group in the undo stack is deallocced.
* The NSInvocation owned by the group is deallocced.
* Now, here's where things start getting hairy. The
NSInvocation has retained the NSManagedObjectContext because it
is its target. And, as things happen, this is apparently the
last retain on the NSManagedObjectContext, because at this
point, it deallocs.
* Within -dealloc, the managed object context sends several
messages, finally resulting in -removeAllActionsWithTarget:
being sent to the undo manager.
* So that it can iterate through the stacks, the undo
manager's -removeAllActionsWithTarget: starts out by attempting
to make a copy of the undoStack, which is still in the process
of having all of its objects removed. Crash.
So, to solve this problem, I implemented a lockout kludge, an
ivar mIsCleaningStacks, in the undo manager.
Its -removeAllActions locks it out while it is removing objects
from its undo and redo stacks, and if
removeAllActionsWithTarget: sees this it doesn't touch them. I
believe this is otherwise harmless, since these stacks are in
the process of having all their objects removed anyhow.
Is this a good case study in why "the only safe thing to do in
your dealloc method is to release instance variables", or have I
misunderstood the problem?
Does a better workaround pop into anyone's mind? The crash does
not occur when using Apple's NSUndoManager, which I presume must
also have some workaround built into it.
Thanks,
Jerry Krinock
#0 0x015f96ce in __CFTypeCollectionRetain
#1 0x016490b0 in CFArrayCreateCopy
#2 0x0028ee31 in -[NSCFArray copyWithZone:]
#3 0x016587ea in -[NSObject(NSObject) copy]
#4 0x0012f318 in -[GCUndoGroup removeTasksWithTarget:] at
GCUndoManager.m:1107
#5 0x0012d89d in -[GCUndoManager removeAllActionsWithTarget:] at
GCUndoManager.m:477
#6 0x01b4b3f1
in -[NSManagedObjectContext(_NSInternalNotificationHandling)
_stopObservingUndoManagerNotifications]
#7 0x01b7c78e
in -[NSManagedObjectContext(_NSInternalNotificationHandling)
_unregisterForNotifications]
#8 0x01b7c5c1 in -[NSManagedObjectContext dealloc]
#9 0x01b695ca in -[NSManagedObjectContext release]
#10 0x015ff528 in CFRelease
#11 0x016298b2 in __CFArrayReleaseValues
#12 0x015ff6f1 in _CFRelease
#13 0x0166d19a in -[NSInvocation dealloc]
#14 0x0012f9cf in -[GCConcreteUndoTask dealloc] at
GCUndoManager.m:1289
#15 0x015ff528 in CFRelease
#16 0x016298b2 in __CFArrayReleaseValues
#17 0x015ff6f1 in _CFRelease
#18 0x0012f614 in -[GCUndoGroup dealloc] at GCUndoManager.m:1183
#19 0x015ff528 in CFRelease
#20 0x016298b2 in __CFArrayReleaseValues
#21 0x0165644e in CFArrayRemoveAllValues
#22 0x0012d7e0 in -[GCUndoManager removeAllActions] at
GCUndoManager.m:455
#23 0x00127c52 in -[SSYDooDooUndoManager removeAllActions] at
SSYDooDooUndoManager.m:101
#24 0x009a63eb in -[NSDocument _releaseUndoManager]
#25 0x009a6898 in -[NSDocument dealloc]
#26 0x00b05b8c in -[NSPersistentDocument dealloc]
#27 0x00115705 in -[Bkmslf dealloc] at Bkmslf.m:2024
#28 0x015ff528 in CFRelease
#29 0x0162c0ed in _CFAutoreleasePoolPop
#30 0x00288dd6 in NSPopAutoreleasePool
#31 0x00288cfe in -[NSAutoreleasePool drain]
#32 0x0060e55f in -[NSApplication run]
#33 0x00606535 in NSApplicationMain
#34 0x00001e67 in main at MainApp-Main.m:19
_______________________________________________
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