Archive for the ‘Programming’ Category

Application Specific Information in Leopard Crash Reports

Friday, January 4th, 2008

Mac OS X Leopard added a lot of new features in the Crash Reporter giving much better crash reports in a number of situations. One of these enhancements you’ll see in applications like DashboardClient is that crash logs can contain an “Application Specific Information” section, with any text that application wants to appear in the crash log. Naturally the ability to add information to the crash report is currently Apple-only secret sauce. So how do they do it?

Searching for Some Clues

First up let’s take a look at what the application specific information looks like in a crash log.

Process:         DashboardClient [3786]
Path:            /System/Library/CoreServices/Dock.app/Contents/
Resources/DashboardClient.app/Contents/MacOS/DashboardClient
Identifier:      com.apple.dashboard.client
Version:         1.5 (1.5)
Build Info:      Dock-5880000~1
Code Type:       X86 (Native)
Parent Process:  Dock [96353]

Date/Time:       2007-11-07 11:46:49.476 +1100
OS Version:      Mac OS X 10.5 (9A581)
Report Version:  6

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000c56c0db3
Crashed Thread:  0

Application Specific Information:
/Library/Widgets/Dictionary.wdgt/
/Library/Widgets/World Clock.wdgt/
/Library/Widgets/Calculator.wdgt/
/Library/Widgets/Weather.wdgt/
/Library/Widgets/World Clock.wdgt/

[...]

Further information with the usual backtrace and image information is shown below this part of the crash log.

OK, so now we know that the DashboardClient can put application specific information into the crash log, let’s take a look at the symbols that DashboardClient references:

$ nm DashboardClient
[...]
         U ___CFConstantStringClassReference
000161fc D ___crashreporter_info__
         U __kLSASNKey
[...]

Aha! Here we’ve got a symbol that looks pretty likely. It’s a data symbol (the D after the address) not a function symbol so it’s not something we need to call to tell the crash reporter something.

Some Experiments

Given that this seems to be a data pointer let’s take a logical jump that it’s probably going to be a pointer to some data: most likely the string of data that will be displayed in the crash log. Given this assumption, it’s time to try some code.

/*
 *  crashinfo.c
 *  AppSpecificCrashInfo
 *
 *  Created by Andrew Wellington on 27/12/07.
 *  Copyright 2007 Andrew Wellington. All rights reserved.
 *
 */

#include 
#include 

int main (int argc, char *argv[])
{
    char **theAppSpecificInfo = NULL;
    theAppSpecificInfo = dlsym(RTLD_DEFAULT, "__crashreporter_info__");

    if (theAppSpecificInfo)
        *theAppSpecificInfo = "My Hovercraft is full of Eels";

    /* Crash with a null dereference */
    char *crasher = 0;
    *crasher = 0;
}

Let’s compile this:

$ gcc -o crashinfo crashinfo.c -framework CoreFoundation

Note that we’re linking to CoreFoundation as that’s the framework that contains the crash reporter symbol. If you don’t link to CoreFoundation the symbol lookup will fail and return NULL.

Time to try and run this:

$ ./crashinfo 
Bus error

Our test crashed as expected, now did it create a crash log with the information we’re expecting? Open up Console from the Utilities folder then find the crash log for “crashinfo”.

[...]
Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000
Crashed Thread:  0

Application Specific Information:
My Hovercraft is full of Eels
[...]

Excellent, we’ve found our crash report and the application specific information is there. So it seems all we need to do is set the symbol to a pointer to a standard C string containing the information that we want.

A Few Thoughts

If you want to use this facility in your application there are some things you should be aware of:

Other frameworks might try and overwrite this value. If you do decide to use this, keep another reference to any dynamically allocated memory. This way you can free it if another framework overwrites the pointer and doesn’t leak memory.

You probably should limit any use of this feature to a subset of Mac OS X versions. At the very least you should only do this for Mac OS X 10.5 (on older versions the symbol either won’t exist, or it might do something totally different, and newer versions could be totally different again and this is an undocumented trick).

If another framework overwrites the data you might not get your application specific information so you still need to be able to extract as much information from crash reports by yourself as you can. This can provide more information than before, but it’s certainly not guaranteed to be there.

After working this out myself, I found a patch Apple adds to Samba on Mac OS X 10.5 that explains this in some detail: http://www.opensource.apple.com/darwinsource/Current/samba-187/patches/add-smb-panic-string-to-crashreporter. The most important thing to note from that patch is this part:

 * NOTE: this is an unsupported interface and the
CrashReporter team reserve
 * the right to change it at any time.

So I guess the answer there is: now you know how to do it, don’t. Enjoy 🙂

And they say Xcode isn’t stable

Monday, March 6th, 2006

andrew 6535 0.1 -6.5 537188 136228 ?? S 28Jan06 109:23.91 /Developer/Applications/Xcode.app/Contents/MacOS/Xcode -psn_0_8519681

That’s right folks, it is currently 22:29, 6th March 2006, and that copy of Xcode has really been running since January 28th. Unfortunately it’s really getting to the stage where I should restart for these updates that keep showing up so it may be cut off in its prime of life…

Ripplin’

Tuesday, December 6th, 2005

Plenty of people have wanted to reproduce the “ripple” effect from Dashboard in Mac OS X. So, for all you people looking to do it, here’s some code to ripple your own windows.

Download Rippler here (52KB).

Enjoy 🙂

Extended Attributes and Tiger’s Rsync

Tuesday, October 11th, 2005

It’s been a while, but never fear I’ve got a nice shiny new bug for you today.

Rsync can in some cases not handle the -E and -‍-delete functions very well when combined together. Because Apple chose to implement resource forks in rsync using their you-beaut-gee-whiz ._ files, when the resource fork doesn’t exist for the file, or indeed the file doesn’t exist at all in the source directory rsync happily attempts to unlink the corresponding ._ file. On an HFS+ volume, clearly this is going to fail, as it doesn’t exist (incidentally on a UFS, Xsan, FAT, etc volume, it’d work just fine, but rsync is still broken).

A Patch

Due to my extreme generosity, or alternatively in an attempt to get away from some software with a name that rhymes with typo, I’ve whipped up a quick fix to this problem. It may not be the best way to fix it, but it works, and it even removes the resource fork from a file if the resource fork should be deleted, but not the file itself. How’s that for slick?

(Yeah, pasting it into a website isn’t all that slick, but I’m too lazy to upload it as a file right now, so tough luck. And WordPress seems to have stuck \ characters before the quote characters. They shouldn’t be there.)

--- rsync-2.6.3/syscall.c	2005-10-11 14:44:42.000000000 +1000
+++ rsync-2.6.3/syscall.c	2005-10-11 15:47:06.000000000 +1000
@@ -53,6 +53,31 @@
 {
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+#ifdef EA_SUPPORT
+	if (extended_attributes
+		&& !strncmp(basename(fname), "._", 2)) {
+		int retval;
+		retval = unlink(fname);
+		if (retval == -1 && errno == ENOENT) {
+			char ftemp[MAXPATHLEN+17];
+			if (snprintf(ftemp, MAXPATHLEN+17, "%s/%s/..namedfork/rsrc", 
+					dirname(fname), basename(fname)+2) >= MAXPATHLEN+17)
+			{
+				errno = ENOENT;
+				return -1;
+			}
+			fprintf(stderr, "%s", ftemp);
+			retval = truncate(ftemp, 0);
+			if (retval == -1 && errno == ENOENT) {
+				return 0;
+			} else {
+				return retval;
+			}
+		} else {
+			return retval;
+		}
+	}
+#endif
 	return unlink(fname);
 }
 

For reference the bug is Radar 4295233.

Report-an-Apple-bug Friday (on Tuesday)

Tuesday, August 23rd, 2005

Dan Wood had an awesome idea for Report-an-Apple-bug Friday. Last Friday was the second Report-an-Apple-bug Friday, so it seemed fitting that I had filed this bug over the weekend.

My bug relates to a small problem I found — a 100% reproducible kernel panic. The panic code is actually the same code Graham and I developed for the Mac OS X Experts Challenge. While Apple fixed the panic caused by panpipes, it turns out that our code triggered another related bug, but not the same bug, which also results in a kernel panic.

Here’s the backtrace (from 10.4.2) for anyone who feels like working out where the bug is by themself:

#0  0x0026d9e4 in threadsignal ()
#1  0x002a529c in catch_exception_raise ()
#2  0x00043340 in exc_server_routine ()
#3  0x0004326c in exc_server ()
#4  0x002a5110 in macx_swapinfo ()

It’s fairly simple (threadsignal isn’t all that long), and follows on from the theme of the panic Amit used in the Mac OS X Expert’s Challenge. It should be fairly easy to work out what the trouble here is with reference to panpipes.

For the record, the Radar ID is 4225451.

I’ve got an idea for my bug for this Friday, so let’s see if we can carry on without Dan for a week, we’d all hate to let him down.

Deliciously Captivating Concepts

Thursday, July 21st, 2005

So drunkenbatman has posted another enthralling interview, this time with Wil Shipley of Delicious Monster. As always it’s an amazing read, so if you haven’t read it, grab a drink (alcoholic of course) and settle down for a nice long read.

Wil’s thoughts on heuristic algorithms are quite interesting. Throughout my degree (and indeed most formal education from what I can tell) much focus has been on provably correct algorithms and provably correct code. Apart from proving algorithms mathematically being boring as hell, in most cases relating to desktop computing the code is simply either too large to prove, or can’t be proved because of the amount of other code is interacts with.

That this sort of proof is a dead end in computer science mirrors what I’ve thought on this for quite a while (of course having to do it for a Uni course tends to increase this feeling). On the other hand, I can certainly see where this sort of proof is relevant — embedded systems involved in medical treatments or nuclear power plants for example. For me at least, this just isn’t what I’m working with.

Perhaps the most interesting decisions that come from this sort of idea is considering what parts of an application should be implemented using this style of programming, and what parts really need to be implemented in a provably correct style (maybe not mathematically provable, because that’ll put you to sleep, but at least logically provable). This decision can make a huge difference to how parts of a program can be implemented, but clearly the concept can’t apply to all parts of most programs, but it is certainly something interesting to keep in mind.

Ultimately, this is a way of providing better feedback to the user to allow them to do what they want, without feeling that they need to fight the computer, clearly something that every application should aspire to.