Nelson Elhage writes a barebones strace(1) using ptrace(2). You tend to pick up a thing or two about Linux programming when you work on reboot-less security patching.
Speaking of Node.js, Heroku—the Ruby deployment platform—started offering experimental Node.js support in April. Some notable Heroku-hosted apps have appeared since, including Github Issues from Cappuccino and Pm: a stack-based language.
Just in case it’s not immediately obvious, I’m going to start linking to interesting websites in the Pointers tag, follow along on that tag-specific Atom feed if you wish. The links will also be included in the main feed.
DARING FIREBALL’s GOING DOWN
John Arbash’s Meliae is the sexy easy library to examine memory usage in your Python runtime, from object-by-object inspection to wholesale statistics. Meliae 0.3.0 was released a few weeks ago.
Undoing just got real fancy, real fancy.
Node.js—an evented I/O framework for server-side JavaScript—seems to be reaching a critical mass in interest, production usage, and libraries. I haven’t seen a platform become so exciting so quickly since Factor last year.
Today’s mystery stack trace is:
#0 0x02b67a93 in objc_msgSend
#1 0x05c2dbb0 in ??
#2 0x004c08d7 in
-[UINavigationController _startTransition:fromViewController:toViewController:]
#3 0x004bb329 in -[UINavigationController _startDeferredTransitionIfNeeded]
#4 0x004c23a0 in
-[UINavigationController pushViewController:transition:forceImmediate:]
#5 0x004bb1c3 in -[UINavigationController pushViewController:animated:]
#6 0x00009803 in -[YourController someAction:] at YourController.m:1821
#7 0x0040ae14 in -[UIApplication sendAction:to:from:forEvent:]
#8 0x0061214b in -[UIBarButtonItem(UIInternal) _sendAction:withEvent:]
#9 0x0040ae14 in -[UIApplication sendAction:to:from:forEvent:]
#10 0x004946c8 in -[UIControl sendAction:to:forEvent:]
#11 0x00496b4a in -[UIControl(Internal) _sendActionsForEvents:withEvent:]
#12 0x004956f7 in -[UIControl touchesEnded:withEvent:]
#13 0x0042e2ff in -[UIWindow _sendTouchesForEvent:]
#14 0x004101ec in -[UIApplication sendEvent:]
#15 0x00414ac4 in _UIApplicationHandleEvent
#16 0x02f43afa in PurpleEventCallback
#17 0x029eddc4 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
#18 0x0294e737 in __CFRunLoopDoSource1
#19 0x0294b9c3 in __CFRunLoopRun
#20 0x0294b280 in CFRunLoopRunSpecific
#21 0x0294b1a1 in CFRunLoopRunInMode
#22 0x02f422c8 in GSEventRunModal
#23 0x02f4238d in GSEventRun
#24 0x00418b58 in UIApplicationMain
#25 0x00002110 in main at main.m:6
And Xcode was kind enough to log an “EXC_BAD_ACCESS” signal.
We know from prior Objective-C experience that “EXC_BAD_ACCESS” means, almost always, access to an object that’s already been freed by the reference counting garbage collector. That is, hitting an object whose retain count already reached zero. So assume this is a memory allocation bug.
We also know the stack trace is useless since the objc_msgSend() is merely the place where the bad access occurred, not the cause. We know from Greg Parker’s weblog that we can read off the ecx and eax registers to get the sent message name (the method call that caused this mess) and the pointer to the object that’s been freed (if we’re lucky). Registers are like variables in Assembly, for readers lucky enough to have never been forced to learn Assembly.
(gdb) p/x $eax
$2 = 0x5a5e8c0
(gdb) x/s $ecx
0x2b6ac10 <__FUNCTION__.13255+742>: "release"
So we’re calling “release” on an object pointer at 0\x5a5e8c0. Going through Parker’s checklist, this pointer is absolutely normal: it’s divisible by 16, the top two and bottom two bits are not set, the bits are not all inverted, it’s not a CF container, and it’s not an ASCII string.
With normalcy in mind, we can now resort to a brute-force grep for “release” calls that could possibly be occur after a pushViewController() begins. Not bad, from a completely worthless stack trace. In this specific case, I knew that a lot of code was executed at view events: viewWillAppear() and viewDidAppear(). Putting a breakpoint on both methods and stepping over each line led me to a double-released NSTimer.
THEN I FELT STUPID, GUYS, REAL STUPID
Moral of the story? Read Greg Parker’s weblog.
subset Child of Person where *.age < 16;
subset Adult of Person where -> $person { 16 < $person.age < 66 };
subset Senior of Person where *.age >= 66;
multi print-name(Child $person) { "Little {$person.name}" }
multi print-name(Adult $person) { $person.name }
multi print-name(Senior $person) { "Old Man {$person.name}" }
Kick. Ass.