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.
- open NSObject and put the following line at the beginning of release():
System.out.println(”Release: ” + toString());
- launch and make the crash happen
- 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 - 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.
- 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.
- restore the
release()
method on the subclass to its original form so that the crash happens again. Remove the
System.out.printlnas well if you no longer feel it’s helpful to you.
- find all callers to
release()
on the subclass.
- 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
and started Eclipse. It crashed and the last thing to be released was
. I added an empty
method to this class and tried to launch again. This time it crashed on
. I added a no-op
to
and tried again. No crash! I then reverted
and turned my attention towards callers to
.
I found two of interest in
and another in
. I decided to look at
first because it seemed more interesting than
. I commented out one of the releases in
and launched only to find that the crash persisted. I then commented out the one in
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
member (the member that contained a reference to an
). I discovered two places where we set the value of
: we
it out in
after calling
on it and we
both
it out and assign it in
. I decide to look in
first because the
looks innocuous enough.
In
we’re releasing the previous value of
, if any. We then go and assign the supplied
to the
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
method that takes an
. The first, taking four integer arguments, constructs and retains a new
so that isn’t our culprit. The second, taking a
, creates a
of the path
instance (which is implicitly
‘d
that takes a
as input. This one looks suspicious! Here we’re passing in the
of the
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
or
call to the
object we’re getting from
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!







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