atom feed20 messages in net.java.dev.rococoa.usersRe: "Invalid memory access" in NSAuto...
FromSent OnAttachments
Duncan McGregorJul 27, 2009 8:48 am 
Michael NagelJul 27, 2009 9:29 am 
Duncan McGregorJul 27, 2009 12:44 pm 
David KocherJul 27, 2009 3:35 pm 
Duncan McGregorJul 27, 2009 3:43 pm 
David KocherJul 27, 2009 4:08 pm 
Andrew ThompsonJul 27, 2009 7:02 pm 
Michael NagelJul 27, 2009 9:28 pm 
Duncan McGregorJul 28, 2009 1:29 am 
Duncan McGregorJul 28, 2009 3:42 am 
Duncan McGregorJul 28, 2009 4:07 am 
Duncan McGregorJul 28, 2009 4:33 am 
Andrew ThompsonJul 28, 2009 4:41 am 
Duncan McGregorJul 28, 2009 5:01 am 
Duncan McGregorJul 28, 2009 11:55 am 
Andrew ThompsonJul 28, 2009 6:17 pm 
Duncan McGregorAug 10, 2009 3:28 am 
Andrew ThompsonAug 10, 2009 8:56 pm 
Duncan McGregorSep 1, 2009 7:59 am 
Andrew ThompsonSep 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