Archive for the 'Mac OS X' Category

Objective-C: Using Instruments to trace messages-to-nil

Friday, January 4th, 2008
In Action_tn.png

In Leopard, Apple added a new tool to the developer tool suite called Instruments. It is a timeline based debugging and performance analysis tool. With a full suite of tools to analyze all kinds of dimensions of performance, correlating all data onto a timeline that can be inspected and navigated at will. And it remembers prior runs so you can compare results before and after changes.

And it fully consumes dtrace.

Clicking through the screenshot at right will show a run of Instruments with a single analysis instrument active.

I created a custom instrument that encapsulates the dtrace script I discussed in Objective-C: Using dtrace to trace messages-to-nil.

I ran the resulting instrument against TextEdit.

What can’t be conveyed by that screenshot is exactly how “live” the data can be examined. You can click and drag on the timeline to select a subset of the run, details of the selected instrument are shown in the table in bottom right, and any given row can be selected to show the backtrace active at the time the sample was taken.

I didn’t want to clutter up the screenshot with lots of data and, thus, didn’t demonstrate the awesomeness that is being able to relate data across multiple instruments, correlated by time.

That’ll be in the next Mac OS X / Software related post.

Click on through for an explanation with screenshots as to exactly how to convert the dtrace script to an instrument.

Read the rest of this entry »

Objective-C: Using dtrace to trace messages-to-nil

Thursday, January 3rd, 2008

Update: There are [at least] two different Objective-C messagers. objc_msgSend() and objc_msgSend_stret(). All of what is written here applies to both however objc_msgSend_stret() is the problematic one when it comes to messages to nil; it is the one used to return structures and, thus, the one that does not necessarily guarantee a zero return.


In my last post on the subject, Adrian Milliner posted a short dtrace script that would log the backtrace for all invocations of objc_msgSend where the first paramater — the target — was nil.

The script is as follows:

pid$1::objc_msgSend:entry
/arg0==0/
{
  ustack();
}

Once saved to a file (in this case objc-nil-trace.d, the trace can be applied to any running Cocoa process via:

sudo dtrace -s objc-nil-trace.d <pid>

The <pid> argument should, obviously, be the process ID of the process to be traced.

It works well enough and is certainly faster than a conditional breakpoint in GDB (likely, orders of magnitude faster), but it is far from a complete solution.

Read the rest of this entry »

Objective-C: Logging Messages to Nil

Wednesday, January 2nd, 2008

This post will make this post useful.

Jim Correia had asked the lazytwitter how to log all method invocations against nil objects.

Some background:

Objective-C is a “nil eats messages” language. That is, if you invoke a method on an object reference that is nil, the runtime will eat the method. It is mostly invisible, only causing outright failures for certain return types that are larger than a pointer — structs, floats, doubles, etc… — at which point, the return value is undefined. Actually, the return value behavior for message to nil isn’t quite that simple.

Regardless of whether you think “nil eats messages” is the correct behavior, that it exists means that you’ll invariably be caught in a situation where a receiver is surprisingly nil. When this happens, it can be a pain to debug for a number of reasons.

Read the rest of this entry »

Objective-C: One Hack to Log Methods

Tuesday, January 1st, 2008

Jim Correia recently tweeted a query asking if it were possible to log all attempts to message through nil in Objective-C.

It is, but not through public API. But that isn’t the subject of this particular post (it’ll be the next post).

In the process of writing up a general solution to Jim’s query, it reminded me of a new feature in Objective-C 2.0 that can be a tremendously handy debugging and exploration hack.

Classes in Objective-C 2.0 can dynamically resolve methods by implementing one or both of the following methods:

+ (BOOL)resolveClassMethod:(SEL)sel;
+ (BOOL)resolveInstanceMethod:(SEL)sel;

The intended purpose of said methods is to allow code to provide an implemention of a method on demand. If the resolver methods can provide an implementation, it uses the function…

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);

… to add an implementation of the requested method to the class. If not, they return NO and the normal forward-or-fail mechanisms kick in.

You can easily create a proxy class that will log a method whenever it is invoked. The simplest form is as follows:

@interface LogEmAsTheyAreInvoked
@end

@implementation LogEmAsTheyAreInvoked
+ (BOOL)resolveInstanceMethod:(SEL)name
{
    NSLog(@"Instance resolving %@", NSStringFromSelector(name));
    return NO;
}

+ (BOOL)resolveClassMethod:(SEL)name
{
    NSLog(@"Class resolving %@", NSStringFromSelector(name));
    return NO;
}
@end

Of course, this is pretty much useless. Without an implementation of…

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;

… the runtime will rapidly decide that all viability is defunct, thus aborting your process. Even the most basic of services, such as allocation, cannot be handled directly. If you need to allocate an instance of the above, use something like:

class_createInstance(objc_getClass("LogEmAsTheyAreInvoked"), 0)

If you want to be particularly tricky, you could supply the proxied class’s instance size instead of the zero and then plug in the method implementations from the original class into the proxied class as each method is invoked. Behavior that tests the class hierarchy may be surprising.

On the slightly less tricky front, you could also create functionality like NSProxy and have the instance of LogEmAsTheyAreInvoked wrap — proxy — some instance of some class. Then it is just a matter of forwarding the method invocations, as desired (which could also directly be used for logging but lacks the nice & automatic “only invoked once” nature of the above methods).

In any case, a neat hack. One of many possible hacks in this vein and not the most general purpose of ’em. Potentially useful for debugging. Your mileage may vary.

Full Twisted as a Zip for Leopard

Saturday, December 22nd, 2007

For those that aren’t familiar with it, Twisted is a truly amazing python based framework for building internet applications. For those that are familiar with Cocoa, Twisted takes a similar philosophy. You configure a server and/or client project with a few basic parameters — easily changed — like IP address, port or ports, UDP or TCP, and Twisted creates a client or server that does exactly that. It responds to or makes connections and has a standard set of hooks for processing data and dealing with all the random network events that may come up.

In other words, it is like a default Cocoa application. It does all the generic Cocoa application things and it is up to you, the developer, to modify it to do what you need to fulfill your specific ideas.

And, like Cocoa, there are a bunch of add-on toolkits, many included with the stock distribution (but not with Leopard, unfortunately), that add significant features. Whereas Cocoa has tools like CoreData to add persistency and change management, Twisted has tools like — say — Conch which adds a full SSH v2 client/server implementation upon which you can build additional tools.

Twisted really is an amazing technology stack. I have encountered nothing like it in any other language or on any platform.

Via PyObjC, Twisted integrates quite nicely with the Cocoa event loop and, thus, is a perfect choice for building and, even, deploying network heavy Cocoa applications.

Twisted is included in Leopard, but only the core. It is enough to build custom networking protocols and the like, but does not include the various modules that ease writing web apps, AIM clients, SSH v2 tools, or that embrace any number of other protocols.

As such, I built a zip file that contains all of the stuff included with the regular Twisted distribution; conch, cred, enterprise, internet, lore, mail, manhole, names, news, persisted, plugins, protocols, runner, spread, tap, trial, web, and words.

It is 32 bit only, ppc and intel.

You can grab a zip from http://www.friday.com/downloads/twisted.zip.

Now, you don’t have to actually unzip it (though you can — shove it somewhere in /Library/Python/). If you add it to the head of sys.path (or PYTHONPATH) before importing anything from twisted (so you don’t get the core stuff from Leopard):

>>> import sys
>>> import os
>>> sys.path.insert(0, os.path.expanduser("~/lib/twisted.zip"))
>>> from twisted import web # this will fail if you get the path wrong

Works well enough for me. If you need the support binaries, they are tar’d up for download at http://www.friday.com/downloads/twisted-bin.tgz (not encapsulated in a directory — just the binaries).

David Reid has been kind enough to toss together Leopard installer packages.

Remote Buddy: Brilliant Bit O’ Software for iPhone & Mac OS X

Thursday, December 13th, 2007
Remote Buddy Dashboard Clipping

I use an AirPort Express to pipe any one of the 17,000 or so tracks from our master iTunes library into my work room / chillout space.

Works great, but getting to the UI just sucks. To select songs or play/pause, I have to wake up my MacBook Pro, unlock the screen, bring up screen sharing, and mess with iTunes. Tedious and annoying.

The moment I first touched an iPhone, I immediately thought “Damn! This would make a great remote for iTunes!”.

And it does!

You just need the right bit of software…

About 2 minutes after grabbing a demo copy of Remote Buddy, I purchased a license. It includes an AJAX based GUI that allows for easy control of iTunes. Way beyond simply play/next/pause/volume, it offers ratings, full access to the library, and — even — the ability to select which speakers to send the music too!

And that is barely scratching the surface. It can also control a slew of other functions on the computer and can even offers screen sharing functionality.

Read the rest of this entry »

PyObjC Xcode Templates now in Subversion

Monday, December 3rd, 2007

Ronald and I realized that the Xcode templates that are included in Leopard didn’t make it into the PyObjC repository.

So, I moved ’em over.

You can find them in the PyObjC subversion repository.

These aren’t just templates, though. See the README.txt.

As it implies, the project-tool.py script is used to effectively convert between Xcode templates and buildable projects. That is, you can create a project that builds/runs like a regular Xcode project, and then easily turn it into a template with the invocation of a simple command line like this:

project-tool.py -k -v --template Cocoa-Python\ Document-based\ Application/CocoaDocApp.xcodeproj/TemplateInfo.plist \
    Cocoa-Python\ Document-based\ Application/ \
    ~/Library/Application\ Support/Developer/Shared/Xcode/Project\ Templates/AA\ Testing/Cocoa-Python\ Document-based\ Application

Or, specifically:

./project-tool --help
Usage: project-tool.py [options]  

    Copies tree of templates or projects from  to .
    Before copying, it cleans up  by removing various bits of garbage.
    After copying, it transforms  by replacing strings with their Xcode
    template counterparts.

    The reverse flag can be used to reverse this process; turning an Xcode
    template into a working project.

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -v, --verbose         verbose
  -k, --kill-dest       erase  (no warning)
  -r, --reverse         reverse transformation (template -> editable project)
  -w, --working         try to make destination into a working project
  -n, --nib             rewrite NIB files to 10.5 text-only format
  -t TEMPLATEFILE, --template=TEMPLATEFILE
                        path to TemplateInfo.plist that should be used during
                        conversion

Nothing remotely Python specific about it. And, as some have noticed, the PyObjC Cocoa templates leverage the new Interface Builder file format (xib) such that all kinds of substitutions happen in the templated interfaces, too. As in: No more MyDocument ever again.

Cocoa Based Smoked Pork

Friday, November 30th, 2007
23 Hour Smoked Boston Butt

As many have tweeted and ‘blogged, there was a bit of Cocoa gathering at Apple this week.

It was mighty cool to hang with so many of the folks that consume our products.

Personally, I was ecstatic to see that so many were embracing garbage collection and finding great success therein.

It is really gratifying to see people run with the tools that we [all of Dev Tech] have pushed out. Damn, you folks are creative!

Anyway, a twitservation (twitter-conversation) — more a half-assed argument– with Wil Shipley combined with the awesomeness of the kitchen led me to cook up 33 lbs of smoked pork for lunch today.

I did it just a bit different this time. Namely, I cooked it slightly longer — 23.5 hours, now that I have looked at the actual wall time — and slightly cooler.

23 Hour Smoked Apples in Pork Fat

I have moved to using a probe thermometer stuck through the gap between halves of the Big Green Egg to monitor temperature. As well, I’m using a large plate setter that coincidentally raises the cooking grid to 1/4″ below the opening of the BGE.

As a result, whatever temperature I set the Stoker too, it will absolutely be the cooking temperature at the interface between fire and food. As a result, this particular pork was cooked at a lower temperature than I have done in the past in that the gradient between cooking grid and top of dome ran as about a 30 degree downward slope (cooking grid @ 230, dome at 200). Previously, the grid probe was typically 1.5″ above grid and, thus, grid temp was probably a good 20 to 30 degrees higher than I intended.

The end result was that the fat and connective tissue was fully rendered, but the cuts of meat still had a slice to them! You could cut it with a fork easily enough, but it still required cutting.

Personally, I found it to be a more pleasing and versatile product than straight up pulled pork.

As an experiment, I halved some apples and placed the halves in a pan under the pork as it cooked with the open face up. No clue what was going to happen.

The end result was a bowl made of apple skin filled with apple stew where the water had been replaced by rendered pork fat.

Universally accepted as delicious. Next time, I’ll make quite a few more and bake them into a pie with little bits of pork fat strewn throughout.

SWT Moving to Cocoa

Friday, November 30th, 2007

A few weeks ago, the SWT folks came out to Apple to learn a bit about Cocoa & Leopard.

Very early in the week, they discovered the BridgeSupport generated XML metadata that describes almost all Objective-C and C APIs on the system (and is included with user installations of Leopard).

Using that, they whipped up a tool that automatically generates a set of Java classes that mirror the Objective-C classes, with all the necessary glue bits underneath.

End result? SWT apps are now Cocoa apps. The goal is to host Eclipse on top of this version of SWT and they already have some success on that front.

Very cool.

All of this work has been pushed back into the SWT repository and they have now put out a call for help from the community.

Can Ruby, Python and Objective-C Co-exist in a Single Application?

Sunday, November 25th, 2007

In short, Yes. But not without some pain.

You can grab an example of the Python and Ruby bridges working together in a Cocoa application from either this downloadable zip or from this Subversion repository (in case something actually changes).

It works. Sort of. Ironically, this likely would have worked better under the pre-BridgeSupport versions of RubyCocoa and PyObjC.

Specifically, RubyCocoa and PyObjC both assume that nothing else might have loaded the dynamic libraries that are automatically generated by the gen_bridge_metadata script. So, either bridge will quite happily attempt to load /System/Library/Frameworks/Foundation.framework/Resources/BridgeSupport/Foundation.dylib and then barf mightily when the other bridge has already loaded the same dylib.

The example is rife with silliness related to catching the resulting exceptions and ignoring them. Worse, the fallout is such that from Foundation import * doesn’t actually cause the Objective-C classes to be defined within the importing module.

There is a back door — objc.lookUpClass() — but this is yet further evidence that, at this time, mixing these two languages in a single Cocoa application is not anything more than a silly hacque (as the SVN repository subdir indicates).

What does it do?

Not much, really.

  • Start with RubyCocoa Application Template (because I can deal with brokeness in Python, I wanted to start with something working in Ruby)
  • NSApp Delegate written in Obj-C
  • Finish loading hooks used to bootstrap PyObjC/Python (with gross exception ignoring goofiness related to the dylib)
  • Bind a table view to an array of dicts where each dict has the key “name” leading to a string value bound through array controller.
  • Array controller bound through app delegate method.
  • App delegate returns array of dictionaries by calling python based NSObject subclass.
  • Python based NSObject subclass composes an array of dictionaries (all python) from a combinatio of Python strings and Ruby strings by calling an instance of a Ruby based subclass of NSObject.

Very little code. Lots of moving parts. Some gears grinding. Maybe even a gear tooth or four missing. Enjoy.