Clever Blog Name

5 notes

A workaround for AESendMessage() hanging on OS X 10.8.2

Shortly after Apple released their OS X 10.8.2 update last week, I started receiving e-mails from iPhoto Library Manager users who were getting timeout errors when trying to use iPLM to transfer photos between iPhoto libraries. iPLM uses Apple events to communicate with iPhoto, and sends the events using the AESendMessage() API in the CoreServices framework. (it doesn’t use AppleScript for reasons of control and efficiency) After some investigation, I believe there is a bug in 10.8.2 that causes this problem, and thought I’d post my findings here in case any other developers were running into similar issues. The bug is filed as number 12424662 and can be found on Open Radar at http://www.openradar.me/12424662

The basic outline of the problem is that sometimes a particular application will get into a state where any events sent to it using AESendMessage (or AESend, for that matter) would not be delivered to the target application, and AESendMessage would simply block until the timeout value was reached, then return an errAETimeout error code. Quitting and relaunching the target application doesn’t change anything, but logging out and logging back in usually seems to fix the problem, at least temporarily. It also appears to only affect one application at a time, e.g. if iPhoto breaks in this way, other apps on the system will continue to function just fine.

After much experimenting with different things, I found a way I was able to get events to flow again, even with the target application in this state. When you set up an Apple event, one of the parameters you need to give is an “address” of the application to which you want to send the event. The Apple event system has several ways of specifying this address, the most common of which are by bundle identifier or by the application’s four character creator code. My code was using the bundle identifier, which looks something like this:

NSAppleEventDescriptor* addressDescriptor = [[NSAppleEventDescriptor alloc] initWithDescriptorType:typeApplicationBundleID 
data:[self.bundleIdentifier dataUsingEncoding:NSUTF8StringEncoding]]; 

NSAppleEventDescriptor* newEvent = [[NSAppleEventDescriptor alloc] initWithEventClass:kAECoreSuite 
eventID:kAEGetData 
targetDescriptor:addressDescriptor 
returnID:kAutoGenerateReturnID 
transactionID:kAnyTransactionID];

What I eventually discovered was, that if I instead used an address descriptor that specified the process ID of the target application rather than just its bundle identifier, then the event would be delivered normally instead of timing out. This of course requires that the application already be running, and requires a bit of additional code to fetch the process ID for the application. This sample code does just that:

NSRunningApplication* runningApplication = [[NSRunningApplication runningApplicationsWithBundleIdentifier:self.bundleIdentifier] lastObject];
pid_t pid = [runningApplication processIdentifier]; 
NSAppleEventDescriptor* addressDescriptor = [[NSAppleEventDescriptor alloc] initWithDescriptorType:typeKernelProcessID bytes:&pid length:sizeof(pid)];

I wrote up a sample project to demonstrate the problem for the bug report. Anyone interested can download the project here. Note that I have still not come up with a way to reliably get an application into this weird state, so running the sample app might not be particularly useful for most people, but you’re welcome to take a look at the code in any case. The “Use pid address” checkbox in the main window is the relevant one - the other checkboxes there were for a bunch of other variations I was trying out, none of which turned out to be the issue. You’re all welcome to play around with it though. :)

My speculative theory is that somewhere in the bowels of the Apple event system, there’s some sort of mapping that it keeps to translate bundle identifiers into process IDs so that events can be delivered to the right app, and it keeps this updated as processes get launched/quit. Somehow on 10.8.2, this can get messed up for a particular application, and any events sent to that bundle ID get swallowed up never to be seen again. Sending directly to the process ID still works though, because it doesn’t need to rely on the messed up internal mapping. Update: It looks like there is a background daemon called appleeventsd which seems to be responsible for this. Killing that process resets things, so you can do that rather than doing a full logout. 

I also saw one other developer, Michael Tsai, mention that he was getting similar reports from another program trying to target his app, SpamSieve, with Apple events. In his case, the events were being sent using typeSignature (the four char code for the app) instead of typeApplicationBundleID, but the symptoms were all the same, so it does appear that this problem can potentially affect any application on OS X once the internal state for it gets messed up.

One additional tidbit, for those who don’t want to use NSRunningApplication (e.g. targeting 10.5 or earlier), this code can also be used to translate from a bundle identifier to a process ID (courtesy of Michael).

   ProcessSerialNumber psn;
   psn.highLongOfPSN = 0;
   psn.lowLongOfPSN = kNoProcess;
   while (GetNextProcess(&psn) == noErr)
   {
       CFDictionaryRef infoCF = ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask);
       if (infoCF)
       {
           NSDictionary *info = [(id)infoCF autorelease];
           NSString *identifier = [info objectForKey:(id)kCFBundleIdentifierKey];
           if ([identifier isEqual:@"com.c-command.SpamSieve"])
               return [info objectForKey:@"pid"];
       }
   }
 

So, hopefully this information will come in useful to some other developers out there. If anyone manages to find a way to reproduce this weird state reliably with a particular application, do get in touch, as I’d love to add that info both to this blog post and to my bug report with Apple.

2 notes

A script to see Time Machine progress via Growl

During long Time Machine backups, I often find myself checking the console for messages from backupd indicating how progress is going, especially when it has to delete a bunch of old backups to make room for the new one, which can take quite a bit of time. I found myself wishing I could just be notified via Growl whenever a new messages popped up in the console, rather than having to check it myself. So, being a programmer, I naturally wrote a script to do it for me.

The script relies on the growlnotify command line tool, one of the extra downloads that you can get with Growl, so you’ll need to download and install that tool first. It’s written in Ruby, and uses the syslog tool to read the messages and then pipe them into calls to growlnotify, so they appear on the screen as Growl notifications. You can find the script as a gist on Github at the link below.

Time Machine Growl script

21 notes

How to make Xcode’s UI work for you (maybe)

Xcode 4 has been out for a while now, but a lot of people are still uncomfortable with its interface and find it awkward to use. I am not in that group, as I’ve actually quite liked the way things are setup overall. This is probably largely because it’s similar to the way I was using Xcode 3 already, in a mostly single-window fashion, but I think I’ve also discovered a few tricks to help ease various parts of my workflow. Many others have probably already discovered these, but I thought I’d share them just in case they prove helpful to anyone.

One Tab Per Task

Tabs are an essential part of my Xcode workflow. I was skeptical of Xcode 4 until I a) discovered it had tabs, and b) discovered some of the details of how they are implemented by Xcode. Heck, I’ve seen some people who still don’t even realize the ability to make tabs exists! After all, they are hidden by default, with no visible tab bar.

Now, with most applications that support a tabbed interface, each tab is typically used to hold a single document, so that you can switch easily between them. I tried this with Xcode 4, but quickly found that the set of files I’m working with at any given time is usually too large for tabs to really be an effective way of managing them. The number of tabs would quickly grow to where I couldn’t find anything, and didn’t end up saving me any time. The key realization I had was that, rather than having one tab per file, I should instead have one tab for each type of task, such as editing, building, debugging, and so forth.

Tab Configuration

One important aspect of Xcode that makes this work well is the fact that each tab remembers its own configuration. This includes things like:

  • Whether the navigator pane (on the left) is visible, and how wide it is.
  • Which navigator is active in the navigator pane (e.g. project, issues, logs, etc.)
  • The filter field and other options at the bottom of the navigator pane.
  • All the analogous stuff for the utilities pane (on the right).
  • Whether the debugger is visible, its size, and whether the variables and/or console is visible
  • Whether the assistant or version editor is enabled.

One thing I’ve seen that annoys a lot of people about Xcode’s interface is that they’re constantly having to fiddle around with resizing things, showing/hiding the navigator/utilities pane, switching the assistant editor on/off, showing/hiding the debugger, and so forth. However, since each tab can remember its configuration, that means you can specialize each tab to handle a particular type of task, and use that tab for that task. You can even give a custom name to each tab by double clicking its name in the tab bar, which will let you type in a name other than that of the currently open file. (this is very non-obvious, and I had to be tipped off by an Apple engineer that this was even possible)

Behaviors

OK, having a different tab for each type of task is fine and all, but that means I still have to switch around tabs all the time, right? Well, not necessarily. With the generous use of the Behaviors capability of Xcode, you can actually automate a lot of the tab switching to happen at the appropriate times. If you’re not familiar with Behaviors, open up the preferences window and click on the Behaviors icon there.

For example, if you have a tab set up specifically for debugging, you can set the “Run pauses” behavior to show the tab named “Debug”, show the debug navigator, and show the debugger pane. That way, whenever you hit a breakpoint, you’ll automatically be switched to that tab, with everything set up and ready to debug your code.

Also worth noting is that you can make your own custom behaviors, using the “+” button down at the bottom of the preferences window, and then assign a custom keyboard shortcut that will trigger that behavior. I’ve co-opted the command-1, command-2, etc. shortcuts, which are used by default by the navigator panes, and instead use them to switch quickly between my custom tabs. This way, anything that can’t be trigger automatically by a built-in behavior, you can instead switch manually without having to take your hands of the keyboard.

My Tabs

To give some concrete examples of what I’m talking about above, I thought I’d just give a quick run through the way I have my own tabs setup. Your workflow will almost certainly differ from mine, but hopefully this will give you some ideas on how you can customize things to the way you work. For context, I generally work on a 1920x1200 display (17” MBP or 24” LED Cinema Display), either in Lion full screen mode or with the Xcode window maximized. I have custom behaviors set up with keyboard shortcuts command-1 through command-6 which let me switch to each of my 6 tabs easily.

Edit

My first tab is used for source code editing, and is generally where I spend the bulk of my time. I like to always have the assistant editor activated and set to “Manual”, so I have two editors side by side. I almost never need to use anything in the utilities pane while editing source, so I keep it closed to give more horizontal space for my two editors. Since I do most of my file navigation using either the jump bar or the “Open Quickly…” menu command, I usually have the Find navigator open on the left, for doing batch find/replace in my project. I of course use the Project navigator whenever I need to mess with my groups or files.

  • Editor Type: assistant, manual
  • Utilites Pane: hidden
  • Navigator Pane: find navigator
  • Debug area: hidden
  • Behaviors: none
  • Screenshot

Debug

As I described a bit above, I have my debugger tab set up so that the debug area is always shown, so I can see variables and the console. The debug navigator is visible, but the utilities pane is hidden. I keep an assistant editor open, which I don’t end up using that often, but it’s usually more useful than having my source file fill the entire width of my screen. The “run pauses” behavior is set up to switch to this tab, and configure it as described, in case anything had previously been set otherwise.

Build

I use this tab for viewing and dealing with issues generated by building, testing, or analyzing code. The workflow that seems to be intended by the Xcode team is to use the Issues navigator to view your build errors/warnings. I, however, hate the Issues navigator. It’s too narrow, it truncates error messages, and it doesn’t let you easily see further details about the problem.

So instead, my setup is to have the “Build generates new issues” behavior set up to a) show the build tab, b) show the log navigator (not the issues navigator), and c) navigate to the current log file. What this does is to show the full build log for the most recent build in the standard editor, which shows all the same issues as the issues navigator, but lets you expand each one to see more details, view the full command line invocation of each build step, and see the environment variables being used for things like shell scripts.

I then have the assistant editor enabled, and set to the “Reference Files” mode in the jump bar. This causes clicking on an issue in the build log to display the relevant file and line in the assistant editor on the right, where I can then correct it. I find this setup to be much better for handling build errors than the default.

Project

One of my favorite parts of the UI revamp done in Xcode 4 is the way that target/project settings are done. The new unified view of how all the build settings are applies is sooooooo much better than the zillion different info windows you had to open up with Xcode 3. To give this the space it deserves, I don’t use the assistant editor in this view, but use the “Levels” view of the project settings. The full screen width gives plenty of space to view the default, project, target, and final build settings side by side.

The project navigator is open on the left, and I have “.xcodeproj” typed into the filter field at the bottom, so that all the projects and sub projects in my workspace are easily visible and can be selected there. The filter string is even remembered by Xcode between relaunches, so you only have to type it in once. I usually also have the utilities pane open, set to the Quick Help inspector, for an easy cheat sheet on whatever build setting I currently have selected.

  • Editor Type: standard
  • Utilites Pane: quick help inspector
  • Navigator Pane: project navigator, “.xcodeproj” filter
  • Debug area: hidden
  • Behaviors: none
  • Screenshot

Model

This tab is a bit of a dual use tab, and is used for both Interface Builder files and Core Data Model files. The main key here is that I want to have a big canvas for moving these objects around on, so I have the standard editor in effect here most of the time. When I’m hooking up outlets and actions though, I will sometimes switch to the assistant editor, to allow easy drag and drop between the interface element and the corresponding header file.

The utilities pane is very important for both of these, so it is always open, to allow for editing of the attributes of whatever object is selected in the main canvas. The Object Library is also open at the bottom, to be able to drag new objects into the model file. I also have the project navigator visible on the left, and have “.xib” entered in the filter field down at the bottom, so that all my IB files are easily accessible from there.

The one thing that’s missing here that I’d like to see in a future version of Xcode is some way to automatically switch to this tab, but only when I’m opening a .xib or .xcdatamodel file. As it is now, I have to remember to manually switch to that tab first before opening a model file. I’m actually not sure what the best way to implement this in Xcode would be - perhaps some way to assign a custom behavior to trigger when opening a certain file type?

  • Editor Type: standard/assistant
  • Utilites Pane: open w/object library
  • Navigator Pane: project navigator, “.xib” filter
  • Debug area: hidden
  • Behaviors: none
  • Screenshot

Console

80% of the time, the smallish console area in the debug tab is enough to view whatever messages are being spit out during a debugging session, but I find fairly often that I need a bigger viewport for reading the console. So, I have a tab dedicated specifically for this purpose. I usually switch to this tab when I’m already in the debug tab, so I have my command-6 behavior set up to do the dirty work. It a) switches to the Console tab, b) shows the debug navigator, c) shows the debugger with Console View only. I then take the horizontal divider between the source code and the console and drag it all the way to the top, so that the console takes up the entire area of the window. This gives me a giant console view for reading through lots of text.

  • Editor Type: standard, but it’s hidden anyway
  • Utilites Pane: hidden
  • Navigator Pane: debug navigator
  • Debug area: shown, console only, dragged all the way to the top
  • Behaviors: keyboard shortcut only
  • Screenshot

So anyway, I hope this description of things gives you some ideas for how to set up Xcode 4 to better fit the way you work. There’s obviously still a lot of room for improvement, but I think things have evolved significantly even since 4.0 came out, so if you haven’t looked much at your workflow in the last couple versions of Xcode, it might be worth revisiting to see if you can automate some of these things to save time and hassle.

0 notes

Debugging an ARC Mac application on Snow Leopard

I’m currently developing a Mac application which uses Apple’s relatively new Automatic Reference Counting (ARC) in place of manual memory management or garbage collection. Thus far, I’ve been doing most of my development and testing using Xcode 4.3 running on OS X 10.7, but I wanted to start to do more thorough testing on 10.6. ARC is supported on both versions of OS X (though with a few minor restrictions on 10.6), but as I quickly discovered when I tried building my application with Xcode 4.2 on 10.6, building an ARC application requires linking against the 10.7 SDK, which is only possible if you’re running Xcode on 10.7. So while I can run the app fine on 10.6, not being able to build on 10.6 makes it a little tricky to use Xcode’s debugger to debug the application.

After a couple days of searching and experimenting, I think I’ve finally come up with a setup that lets me debug my application relatively easily on 10.6 while still using ARC, and I figured I’d document it here. In my particular case, I’m running 10.7 on my main machine, then using VMware Fusion 4 to run an instance of 10.6 in a virtual machine, but the setup explained here should work just as well with two machines connected on a network.

Workspace setup

The first step in the process is to get things set up so that you can run your application from within Xcode 4.2 on your 10.6 machine. To access the application that is built on the 10.7 machine, I used standard file sharing in the Finder to connect from one machine to the other (I initially tried using VMware’s folder sharing feature, but it turned out to have some weird quirks and not work correctly a lot of the time).

I wanted to open my Xcode workspace file in Xcode 4.2, but I figured that directly using the same workspace file that was being used by Xcode 4.3 on the other machine might not be the best idea, in case one saved changes under the other one’s nose, so I created a separate copy of the workspace (still one project file though) and opened that in Xcode 4.2. Later on, when I discovered I didn’t need to still have Xcode 4.3 running on my 10.7 machine (more on that later), this step turned out not to be necessary, but if you do want to have both versions of Xcode running at the same time, it’s probably best to avoid having them confuse each other.

Since we don’t want to actually build anything in Xcode 4.2, use the “New Scheme” command and create a scheme with its target set to “None”, so no building will take place when using that scheme. Once the scheme is created, edit the scheme, and click on the “Run” action. Select “Other…” from the Executable pop-up menu, then go and select the built application that’s residing on your 10.7 machine. It’ll be hidden away in the Xcode “DerivedData” folder, the default location being ~/Library/Developer/Xcode/DerivedData. Once that’s set up, clicking the “Run” button with that scheme active should run the application from within Xcode.

Debugging symbols

You’ll notice when running the app that gdb spits out a whole bunch of messages to the console complaining about not being able to find various .o files. Normally, gdb looks here for debugging symbols that it uses to be able to display variables, stack traces, and other information while debugging. However, the .o files are referenced by absolute path when built, so when that information is stored on the 10.7 machine but being accessed from the 10.6 machine, the paths are different, so gdb is unable to find those files.

The solution to this is fortunately pretty easy. In Xcode on the 10.7 machine, bring up the build settings for your application target, find the “Debug Information Format” setting, and change it to “DWARF with dSYM File”. This will cause a separate .dSYM file to be generated alongside your application when built, which contains all the debug information in one place and doesn’t depend on absolute paths. When running the app on 10.6, Xcode should be able to pick up the debugging info it needs from the dSYM file.

Source Code

We’re now able to debug the application, but if we hit a breakpoint, Xcode shows us a disassembly of our code rather than the actual source code. This is a similar problem to above, where gdb is looking for the source code files using absolute paths, but the paths are now different when running on the 10.6 machine. The best workaround I’ve found for this is the gdb command “set pathname-substitutions”, which basically allows you to tell gdb to treat any file paths starting with a particular prefix as though they started with a different prefix.

So in our case, you would want to run “set pathname-substitutions /path/to/source/on/10.7/machine /path/to/source/on/10.6/machine”, of course putting in whatever the paths are on your particular setup. Since I didn’t want to have to type this in manually every time we start a new gdb session, I decided to create a .gdbinit file in my home directly and add the command there. gdb will automatically execute commands in that file whenever it starts, so that automates getting the source files to show up.

Automating the build

I had things pretty well set up at this point, where I could switch over to Xcode 4.3, edit and build my project, then go back to Xcode 4.2 and debug the newly built application from there. This quickly got tiring though, so I looked for some way to automate this process as well.

I did this by taking advantage of the “pre-actions” provided by Xcode when setting up a scheme. This lets you specify an arbitrary script that should be run before running your executable each time. To set one up, select “Edit Scheme” from the Product menu, click on the disclosure triangle next to the “Run” action in the scheme editor, then click on the “Pre-actions” item that’s revealed. Click the “+” button at the bottom and select “New Run Script Action” from the pop-up menu.

The actual building can be done using the xcodebuild command line tool, but of course the tricky part is that we want that to be done on the remote 10.7 machine instead of the 10.6 machine the script is being run from. Fortunately, this can be done pretty easily through ssh, so your script would look something like:

ssh username@lion-machine-name.local “xcodebuild -workspace ‘/path/to/my.xcworkspace’ -scheme ‘My Scheme’ -configuration ‘Debug’ build”

You’ll need to have ssh set up so you can connect using a public/private key pair, because otherwise the script will prompt you to enter your password to log in to the remote machine and just hang there. If you need to set this up, just search the web for “ssh keys howto” and you’ll be given plenty of guides on setting ssh up.

So, now that that’s set up, clicking the “Run” button in Xcode 4.2 will fire off a build on the 10.7 machine, then when it’s done, run the newly built product on the 10.6, all ready for debugging! The only thing I haven’t figured out yet is how to tell when a build error occurs on the remote machine, so you sometimes still do have to switch back over to the Lion machine and build manually in Xcode 4.3 there if you want to see the details of the build error.

Quirks

I have run into a couple quirks with this setup still. If I have the project open in both Xcode 4.2 and 4.3 at the same time, sometimes both copies of Xcode got into some weird indexing loop, where one will start indexing, and somehow that will trigger the other copy to reindex files on its end, and so forth in a never ending loop. I’m still not quite sure why this was happening, since each one has its own indexing data stored within each machine’s home folder, but if this happens to you, you’ll probably just need to quit one of the two copies of Xcode.

Occasionally, when attempting to run the app, I’ll get an error message from dyld saying that it couldn’t find one of the frameworks that’s embeddde inside the app bundle. The framework is indeed there though, so I’m not quite sure why this happens. I assume it must be some odd networking quirk running the app via file sharing. Usually either just trying a few times, rebuilding the app again, or poking at the build folder in the Finder will clear things up. I might investigate putting some “touch” commands in my pre-run script to see if that cuts down on instances of this.

0 notes

A new blog for a new day… or something

This is the inaugural post of this new blog, wherein I talk about how I’ve never been good at blogging regularly in the past, but this time I’m actually gonna post stuff, for reals. I know this, because I think I’ve written this post two or three times before over the years. But for reals this time!

I have posted the occasional developer/opinion piece on my blog over at my company blog at Fat Cat Software, but I think I’d like to keep that blog for just company related topics, with other stuff going over here. Dunno yet what I’ll post, but setting up the blog is the first step, so we’ll see how things go.