Following up on debugging innuendos, here’s an example of scratching your head for something apparently stupid.
Working on an iOS project, you need the simulator application a lot. So I was just working on a somewhat huge project when (seemingly) out of the blue, the simulator stops working.
Launching it manually makes it crash, launching it through Xcode only yields in a completely black window.
No worries, just delete the simulated contents (through the “Reset Contents” menu item), and try again.
OK then. Delete the simulated contents manually (from ~/Application Support/iPhone Simulator/).
Aaaaaaargh. Delete the preferences, the caches and the simulated contents, and try again.
Breathe. Call up a friend, and chat for a bit about nonsense and then pop the question. “Just reinstall the devtools, man”. Except it’s a long process. But I’ve wasted an hour already, so…
Reinstalling on top of an existing installation (same version): 20min and… No go.
De-installing by trashing the Developer folder, reinstalling: 30min and… No go.
Maybe something wasn’t uninstalled properly. Use the De-installer script, and reinstall: 40min and… No go.
Alright… Ping a friend at Apple, convey your will to hang yourself with the last non-wireless mouse you have, and whine a bit. “Reinstall the OS, man”. Yea well. No, I have to draw the line somewhere.
So what’s left? Facts:
- It runs well on another session on the same mac
- It runs fine on another computer with exactly the same setup (OS/Tools/Project)
- It crashes on a weird exception: [__NSArrayM insertObject:atIndex:] : object can’t be nil.
- I haven’t installed anything new, so it has to be something from before that got corrupted somehow, that can’t be the tools (reinstalled), the prefs (reset), or the contents (ditto)
So digging a little further, it’s happening when the application loads its main nib. It’s gotta be something inserted in a menu, right? As there’s nothing else left in the contents…
So, firing up Terminal it is then. Then use the “fs_usage” command to figure out after which one of the files it’s loading that the app crashes. It links back to the MainMenu.nib. Not a great help.
Code injection (loading a new category that would supersede __NSArrayM’s insertObject:atIndex: selector, in order to nil-proof the loading) is out of the question with macos applications, so it’s assembly-reading all the way.
Breaking on the exception (catch throw in gdb, but you have to set it after you’ve hit a breakpoint, though) lets me examine the stack at the time of crash, to figure out what the arguments might be. Obviously, it is “nil”, so no help there. Got to figure out a way to break on a “clean” call to that function just before the exception. Ideally, breaking on the previous insert in the same function that worked well.
Let me just say that this can’t really be done.
And then, the click moment: why don’t I print out “self” to see what’s already in there?
Thought breeds deed, and the array is a list of process names. Obviously not every process, since another session works fine, so it must be the list of user processes. Hold on, it seems more complicated than that. It’s a list of user processes and their children, even if they are run with a setuid.
And, like that, the solution is found: I had a disk repair going on (with Media Scanner, the best bad blocks utility out there). Unfortunately, it appears that this process either doesn’t have a bundle id or a name in the process list, or something that yields a nil name.
So, to sum it up: I’ve been stumped a whole day because Apple’s iOS Simulator makes a list of all running processes on my mac before starting up (list that incidentally doesn’t show up anywhere in the interface) and doesn’t like one of them, which is totally unrelated to development anyway.