For many years now we've had an integrated crash reporting system. This has helped improve the stability of our applications immensely (often report now start out with “Wow, this is the first crash I've seen…”). But, it hasn't always been clear (especially in the alpha or beta timeframe) how well we were doing on overall stability. We could guess by counting the number of crash reports vs. an estimate of the number of active users, but that wasn't very convincing.
Near the beginning of June, I added some support to our software update and crash logging frameworks to keep track of things like:
- total times the application has been launched
- total number of crashes
- total amount of time the application has been running
(As always, our software update system reports its information without including any personal details, and can be disabled entirely if so desired.)
Using this, we can now chart the total number of hours OmniFocus has been running vs. the total number of crashes (reported or not!). As the pool of people testing OmniFocus goes up, or some testers go idle, or some user with large number of crashes isn't reporting them, we don't have to wonder as much how that affects our average crash rate.

After my latest crash fix, our rate has improved to about 8000 hours per crash. We aren't sure yet what constitutes a reasonable lower limit for hours/crash, but this does let us notice when a fix we've made actually is addressing the issue. We aren't yet tracking the number of hours that the application is active (an hour spent hidden counts the same as an hour spent in full use). Whether this matters, when averaged across a large number of users, is open to question.
Still, there are only 8760 hours in a year, so if we can get above that, we'll be feeling pretty good.
Now that OmniFocus is sticking its toes out the door, this seems like a good time to remind everyone about best practices on reporting problems. Crash reports are especially important and should receive extra care.
- Please report every single crash you hit, even if you don't know how to reproduce it yet. Include any details of what you were doing leading up to the crash. We can then correlate reports from different users to narrow down the cause, even if no one person can reliably reproduce the problem.
- If you are comfortable doing so, include your document as a starting point (for OmniFocus, this is in ~/Library/Application Support/OmniFocus). If you have qualms about sending your data, skipping this is OK. Another option is to export your file to a backup and then trim down that copy to include only the portions necessary to reproduce the problem.
- List the exact steps to reproduce the problem, starting from the file you included or from an empty document. It is hard to be too specific: for example, you might be tempted to say “I deleted the second task of the project 'Foo'”, but this doesn't make it clear whether you used the delete key, a main menu item, a context menu, invoked an AppleScript, or picked up the task and dragged it to the trash. In some cases, the distinction matters. When in doubt, describe the physical actions you used (“press key X”, “clicked button Y”).
- If the proper behavior isn't obvious (“don't crash”), tell us what you expected to happen. Maybe you have a perspective on a design question we haven't considered or that we should reconsider.
With crash reports in particular, it is important to include reproducible steps. Sometimes this isn't possible, and that's fine—please report the crash anyway with whatever details you have. With a large enough pool of people, someone will be able to figure out how to reproduce it.
Crash reports are CC'd directly to the entire OmniFocus engineering team. If you include reproducible steps, we'll typically stop whatever else we're working to fix it immediately.
Wim came up with a neat trick a while back that we've used to find and fix several bugs in our software, and to file a bunch of Radars. There are several messenger dispatch functions in the Objective-C runtime. Of particular interest here are objc_msgSend_fpret and objc_msgSend_stret. These are used by the compiler when calling a method that returns a float or struct, respectively.
Depending on your architecture, the result of such a message can be undefined when sent to nil. Messaging nil is very useful most of the time, but you can introduce rarely manifesting bugs in this case.
Looking at the disassembly for these two functions in gdb, though, gives us an easy way to catch them. Under 10.4.8/x86, we see the following:
(gdb) x/50i objc_msgSend_fpret
0x90a573c0 : mov 4(%esp),%eax
0x90a573c4 : test %eax,%eax
0x90a573c6 : je 0x90a57420
0x90a573c8 : mov 0(%eax),%eax
...
That is, load the first argument, check for zero, if so jump to 0x90a57420.
Likewise, in objc_msgSend_stret:
(gdb) x/50i objc_msgSend_stret
0x90a57340 : mov 8(%esp),%eax
0x90a57344 : test %eax,%eax
0x90a57346 : je 0x90a573a0
0x90a57348 : mov 0(%eax),%eax
...
In our ~/.gdbinit we can have:
# Nil-handling path for objc_msgSend_fpret.
b *0x90a57420
comm
p (char *)$ecx
end
# Nil-handling path for objc_msgSend_stret.
b *0x90a573a0
comm
p (char *)$ecx
end
(where the print command shows the selector).
Omni's currently looking for a coder to help us implement our award winning apps. Send in a resumé and join the fun!
I'm hopelessly geeky, but here is an OmniPlan document that shows the dependencies for gaining entrance to Mount Hyjal in the Burning Crusade.
Obviously the estimates will need to be tweaked as each person sees fit. Thanks to Aerdrig for the pretty graph that I used to set up the dependencies.
Occasionally I'll stumble across an image on the web that looks strangely familiar. Aah, the smoothness of line, the roundness of clouds, ... smells like Graffle! Most recently I was wasting time on digg and saw some interesting network packet diagrams. Looking at the PDF file, I could plainly see the evidence!
This got me to wondering—how many Graffle-generated PDF documents are out there. Google to the rescue!
This turned up a bunch of interesting and strange results. Here are my favorites from the first five pages of hits. What other fun Graffle documents can you find on Google? Gooffle, the sport of kings!
- Pretty pictures, really, that's what drew me to this one. That and the math (presumably from TeXshop and/or EquationService).
- Ruby Method Dispatch. The Kernel bone's connected to the Object bone, the Object bone's connected to the Module bone… Nice use of line hops, too.
- More line hops. Someone probably understands this graph, but I just like trying to count the line hops.
- State of Mac Web Design, In which we learn that we need to send one Mr. Teague an OmniWeb license. And that he considers Safari only half a browser.
- Worms! These guys are probably pretty smart and serious, but their box titles hint at humor. The Worm Menace!
- Vassar Router Setup gives us advice that every student should learn:
DO NOT use the “internet” port (put a piece of tape over it)
- Things that make you go, “huh?” A WinXP memory layout diagram, made on a Mac.
- DOE Annual Review Fermilab pimps their tape storage.
- DOJ this time. I don't want to live in this neighborhood.
- Cake or death? A nice advert for a talk about death, but at the bottom there is a reprieve of refreshments.
Rawr, I'm a panther! Now that I'm done wasting time on digg and google, I have something else to go do…
Since I just committed my last OmniDazzle fix (at least until QA tracks me down…), I thought I'd share a fun graph.
Omni has been using source control systems like CVS and Subversion since forever. A while back, we converted to Subversion and imported most of our CVS repository (none of our old consulting projects, just our apps). Here is a graph of the number of commits in our repository over the last 13 years.

Thanks to a kind person who sent me their kGTD file, I've fixed a crasher when upgrading to the 0.83 release of Kinkless. This fix, and some fixes for printing issues (along with a few other odds and ends) will be coming in a 3.6 beta 2 release in a few days.
Reproducible test cases are almost better than coffee.
[Update: OO 3.6 beta 2 is now out. If you are using KGTD, General Zod says you should update right away!]