No Business Naming Things

Where sassy women wear jaunty hats.

No Business Naming Things header image 2

You Heard The Man, Blow Your Brains Out!

November 20th, 2007 · 5 Comments

So you’ve read Steve’s blog and you’re all excited to help out with the Cocoa port (as you should be). But then you grab the code and you’re worried. Just how do you do anything with this? This is all so new and rough. You’re plodding along, kicking the tires, and suddenly you’re assaulted by a segfault in the native library. Your pant burst into flame, your dog gives birth to kittens, and you start singing soprano. Where do you start? How do you track this issue down?

There are going to be crashes. When you come across one that smells like a segfault here’s a simple (if somewhat laborious) method to track it down.

  1. open NSObject and put the following line at the beginning of release():
    System.out.println(”Release: ” + toString());
  2. launch and make the crash happen
  3. In your Console view you should see reams and reams of lines like this:

    Release: org.eclipse.swt.internal.cocoa.NSBezierPath@dd4cd3
    Release: org.eclipse.swt.internal.cocoa.NSAttributedString@deb323
    Release: org.eclipse.swt.internal.cocoa.NSBezierPath@c2ee77
  4. Starting from the bottom up locate each subclass of NSObject (such as NSBezierPath) and either override it’s
    release()

    method such that it’s empty or alter the existing

    release()

    method so that it does nothing.

  5. repeat steps 2-4 with each successive subclass you encounter until the crash stops happening. Something pertaining to the last class you changed is probably your culpret.
  6. restore the
    release()

    method on the subclass to its original form so that the crash happens again. Remove the

    System.out.println

    as well if you no longer feel it’s helpful to you.

  7. find all callers to
    release()

    on the subclass.

  8. from here it gets fuzzy. You’ll need to start commenting out calls to
    release()

    and see if any particular disposal of the object is responsible. Perhaps

    release()

    is called but the object is still held in SWT and later used for another purpose. If commenting out any particular

    release()

    call doesn’t stop the crash from happening you start looking at how the object is being retained. If we’re using an object from another structure are we calling

    retain()

    or

    copy()

    on it? We should never be

    release()

    -ing anything we haven’t previously

    retain()

    ‘d (explicitly or implicitly)

Here’s how I applied this technique to find the crash Steve alluded to that was preventing Eclipse from coming up. I added my System.out statement to

NSObject.release()

and started Eclipse. It crashed and the last thing to be released was

NSAutoReleasePool

. I added an empty

release()

method to this class and tried to launch again. This time it crashed on

NSBezierPath

. I added a no-op

release()

to

NSBezierPath

and tried again. No crash! I then reverted

NSAutoReleasePool

and turned my attention towards callers to

NSBezierPath.release()

.

I found two of interest in

GC

and another in

Path

. I decided to look at

GC

first because it seemed more interesting than

Path

. I commented out one of the releases in

GC.setClipping()

and launched only to find that the crash persisted. I then commented out the one in

GC.dispose()

and still the crash persisted. This one was going to be a bit more difficult than a simple disposal. I turned my attention towards all the places we set the

data.clipPath

member (the member that contained a reference to an

NSBezierPath

). I discovered two places where we set the value of

data.clipPath

: we

null

it out in

GC.dispose()

after calling

release()

on it and we
both

null

it out and assign it in

setClipping

. I decide to look in

setClipping()

first because the

dispose()

looks innocuous enough.

In

setClipping

we’re releasing the previous value of

data.clipPath

, if any. We then go and assign the supplied

NSBezierPath

to the

data.clipPath

member. Hmm. Interesting. We’re releasing an object we haven’t retained in this method. We must be retaining it elsewhere, right? Let’s look. There are four callers to the

setClipping()

method that takes an

NSBezierPath

. The first, taking four integer arguments, constructs and retains a new

NSBezierPath

so that isn’t our culprit. The second, taking a

Path

, creates a

copy()

of the path

NSBezierPath

instance (which is implicitly

‘d). This one is probably good too. Next up at bat is

setClipping

that takes a

Region

as input. This one looks suspicious! Here we’re passing in the

NSBezierPath

of the

Region

object without retaining it. Decrementing the reference count of an object you haven’t previously increased the reference for is a surefire way of causing grief. If we simply add a

retain()

or

copy()

call to the

NSBezierPath

object we’re getting from

Region.getPath()

the crash should go away. And lo it does.

This virgin Cocoa port represents an incredibly awesome opportunity for the community to shine. People have been crying for a Cocoa port for years now and now there’s an opportunity for industrious contributors to grab the bull by the horns and make it happen. The rewards (in terms of good will alone) are enormous. The SWT team has done a remarkable job bootstrapping the effort to get this port underway and it would be a real shame if the community didn’t jump on board and make it happen. Long term we absolutely NEED Cocoa for continued existence on the Mac – Carbons days are numbered. If you’re an Eclipse user on the Mac you owe it to yourself and the community to participate in this as best you can. If you don’t feel you’re able to submit patches then well-investigated bug reports will do. This is a huge amount of work and every little bit helps!

Tags: Eclipse

5 responses so far ↓

  • 1 AlBlue // Nov 20, 2007 at 3:53 pm

    Couldn’t agree more :-) I’m even having to prematurely upgrade to Leopard in order to help out.

  • 2 Chris Aniszczyk (zx) // Nov 20, 2007 at 4:16 pm

    Go get ‘em pookie!

    You tell ‘em, put up or shut up!

  • 3 Ed Merks // Nov 20, 2007 at 6:25 pm

    This is a very nice call to action Kim. I hope the community takes notice!

  • 4 tercumenette // Dec 4, 2007 at 3:34 am

    very nice thanks for sharing

  • 5 Jim // Dec 10, 2007 at 11:42 pm

    Hi

    Noob question, but can you share any insight on how to actually run Eclipse through the Eclipse debugger?

    I’ve got the latest Eclipse code from CVS and modified the SWT .classpath as per http://www.eclipse.org/swt/cvs.php , but launching the “Eclipse Editors Demo” leads to lots errors in required plugins, for example: org.eclipse.core.runtime.osgi

    Thanks in advance.

Leave a Comment