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:Duncan McGregor (dun@oneeyedmen.com)
Date:Jul 27, 2009 3:43:34 pm
List:net.java.dev.rococoa.users

On 27 Jul 2009, at 23:36, David Kocher wrote:

I don't think we have to understand the implementation details. We know from experience, well informed sources, documentation [1] and warnings printed to stderr in newer versions of OS X that we should not call both release and drain.

My point though is that I am unable to reproduce the crash I know that we had. Michael's code does crash, but it is accessing str from 2 threads and I'm not convinced that it is safe.

Currently these tests are all passing

public class NSAutoreleasePoolTest {

private ID idString = Foundation.cfString("test"); private Throwable thrown;

public NSAutoreleasePoolTest() { Foundation.cfRetain(idString); RococoaTestCase.assertRetainCount(2, idString); }

@After public void tearDown() { Foundation.cfRelease(idString); }

@Test public void drainReleasesContents() { NSAutoreleasePool pool = NSAutoreleasePool.new_(); Foundation.sendReturnsID(idString, "autorelease"); RococoaTestCase.assertRetainCount(2, idString); pool.drain(); RococoaTestCase.assertRetainCount(1, idString); }

@Test public void releaseReleasesContents() { NSAutoreleasePool pool = NSAutoreleasePool.new_(); Foundation.sendReturnsID(idString, "autorelease"); RococoaTestCase.assertRetainCount(2, idString); pool.release(); RococoaTestCase.assertRetainCount(1, idString); }

@Test public void cfReleaseReleasesContents() { NSAutoreleasePool pool = NSAutoreleasePool.new_(); Foundation.sendReturnsID(idString, "autorelease"); RococoaTestCase.assertRetainCount(2, idString); Foundation.cfRelease(pool.id()); RococoaTestCase.assertRetainCount(1, idString); }

@Test public void drainDoesntLeadToCrashInFinalize() { NSAutoreleasePool pool = NSAutoreleasePool.new_(); RococoaTestCase.assertRetainCount(1, pool); Foundation.sendReturnsID(idString, "autorelease");

pool.drain(); RococoaTestCase.assertRetainCount(1, idString); 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(); } }

@Test public void drainOnNotMainThreadDoesntLeadToCrashInFinalize() throws Throwable { Thread t = new Thread("test") { public void run() { try { drainDoesntLeadToCrashInFinalize(); } catch (Throwable t) { thrown = t; } }}; t.start(); t.join(); if (thrown != null) throw thrown; }