Permalink
Browse files

fix crash when deallocating a weak reference target that still has KV…

…O observers registered
  • Loading branch information...
1 parent 3c0c1da commit 540e2b008b7a289f948b6702e9fc43fe82a5199e @mikeash committed Mar 16, 2011
Showing with 27 additions and 0 deletions.
  1. +9 −0 Source/MAZeroingWeakRef.m
  2. +18 −0 Source/main.m
@@ -452,6 +452,15 @@ static Class CreateCustomSubclass(Class class, id obj)
if(isKVO)
{
SetSuperclass(class, newClass); // EVIL EVIL EVIL
+
+ // if you thought setting the superclass was evil, wait until you get a load of this
+ // for some reason, KVO stores the superclass of the KVO class in the class's indexed ivars
+ // I don't know why they don't just use class_getSuperclass, but there we are
+ // this has to be set as well, otherwise KVO can skip over our dealloc, causing
+ // weak references not to get zeroed, doh!
+ id *kvoSuperclass = object_getIndexedIvars(class);
+ *kvoSuperclass = newClass;
+
RegisterCustomSubclass(newClass, classToSubclass);
}
}
View
@@ -434,6 +434,24 @@ static void TestKVOReleaseNoCrash(void)
[target setKey: @"value"];
+ // destroying target without removing the observer tosses a warning to the console
+ // but it's necessary in order to test this failure mode
+ [target release];
+ [ref target];
+
+ [ref release];
+}
+
+static void TestKVOReleaseCrash(void)
+{
+ KVOTarget *target = [[KVOTarget alloc] init];
+
+ [target addObserver: target forKeyPath: @"key" options: 0 context: NULL];
+
+ MAZeroingWeakRef *ref = [[MAZeroingWeakRef alloc] initWithTarget: target];
+
+ [target setKey: @"value"];
+
[target release];
[ref target];

0 comments on commit 540e2b0

Please sign in to comment.