| From | Sent On | Attachments |
|---|---|---|
| Duncan McGregor | Jul 27, 2009 8:48 am | |
| Michael Nagel | Jul 27, 2009 9:29 am | |
| Duncan McGregor | Jul 27, 2009 12:44 pm | |
| David Kocher | Jul 27, 2009 3:35 pm | |
| Duncan McGregor | Jul 27, 2009 3:43 pm | |
| David Kocher | Jul 27, 2009 4:08 pm | |
| Andrew Thompson | Jul 27, 2009 7:02 pm | |
| Michael Nagel | Jul 27, 2009 9:28 pm | |
| Duncan McGregor | Jul 28, 2009 1:29 am | |
| Duncan McGregor | Jul 28, 2009 3:42 am | |
| Duncan McGregor | Jul 28, 2009 4:07 am | |
| Duncan McGregor | Jul 28, 2009 4:33 am | |
| Andrew Thompson | Jul 28, 2009 4:41 am | |
| Duncan McGregor | Jul 28, 2009 5:01 am | |
| Duncan McGregor | Jul 28, 2009 11:55 am | |
| Andrew Thompson | Jul 28, 2009 6:17 pm | |
| Duncan McGregor | Aug 10, 2009 3:28 am | |
| Andrew Thompson | Aug 10, 2009 8:56 pm | |
| Duncan McGregor | Sep 1, 2009 7:59 am | |
| Andrew Thompson | Sep 1, 2009 6:12 pm |
| Subject: | Re: "Invalid memory access" in NSAutoreleasePool.finalize | |
|---|---|---|
| From: | Michael Nagel (nag...@jotomi.de) | |
| Date: | Jul 27, 2009 9:29:18 am | |
| List: | net.java.dev.rococoa.users | |
Hi Duncan,
The bug appears to be triggered mostly (only?) in multithreaded applications. I guess it might rear its head when a pool in one thread catches an autorelease that originates in an object that was created in another thread. Or maybe it's something completely different. Here's a class that crashes about nine times out of ten when I run it on my machine. Unfortunately, I can't build a proper test case because I'm not familiar with the process of making a multithreaded test.
------------------
import java.lang.ref.WeakReference;
import org.rococoa.cocoa.NSAutoreleasePool; import org.rococoa.cocoa.NSString;
public class NSAutoreleasePoolThreadTest implements Runnable {
static NSString str; NSAutoreleasePool pool;
public void run() { pool = NSAutoreleasePool.new_();
System.out.println(str.substringFromIndex(4));
pool.release(); }
public static void main(String[] args) { NSAutoreleasePool pool_main = NSAutoreleasePool.new_(); str = NSString.CLASS.stringWithString("teststr");
NSAutoreleasePoolThreadTest arptt = new NSAutoreleasePoolThreadTest();
Thread thread = new Thread(arptt); thread.start(); try { thread.join(); } catch (InterruptedException e) { }
WeakReference<Object> reference = new WeakReference<Object>(arptt.pool); arptt.pool = null;
pool_main.release();
while (reference.get() != null) { System.gc(); } }
}
Cheers, Michael
On 27.07.2009, at 17:49, Duncan McGregor wrote:
I know that I said that I knew how to fix this, but now that I come to try, it turns out that I can't reproduce it!
I've just checked in NSAutoreleasePoolTest
@Test public void drainDoesntLeadToCrashInFinalize() { NSAutoreleasePool pool = NSAutoreleasePool.new_(); RococoaTestCase.assertRetainCount(1, pool); pool.drain(); pool.release(); Foundation.cfRelease(pool.id()); RococoaTestCase.assertRetainCount(1, pool);
// wait until object has been GC'd WeakReference<Object> reference = new WeakReference<Object>(pool); pool = null; while (reference.get() != null) { RococoaTestCase.gc(); }
for (int i = 0; i < 20; i++) { RococoaTestCase.gc(); } }
Notwithstanding my previous theories, none of drain, release or CFRelease seem to dent the pool's retain count, so that it is fine to be CFReleased again in finalize.
Can anyone confirm my findings please, and / or provide a failing test case?
Cheers
Duncan





