If you’ve been debugging Gecko, you’ve probably hit the frustration of having the code you’re inspecting being called asynchronously, and your stack trace rooting through
NS_ProcessNextEvent, which means you don’t know at first glance how your code ended up being called in the first place.
Events running from the Gecko event loop are all
nsRunnable instances. So at some level close to
NS_ProcessNextEvent, in your backtrace, you will see
Class::Run. If you’re lucky, you can find where the
nsRunnable was created. But that requires the stars to be perfectly aligned. In many cases, they’re not.
There comes your savior: rr. If you don’t know it, check it out. The downside is that you must first
rr record a Firefox session doing what you’re debugging. Then,
rr replay will give you a debugger with the capabilities of a time machine.
Note, I’m kind of jinxed, I don’t do much C++ debugging these days, so every time I use
rr replay, I end up hitting a new error. Tip #1: try again with rr’s current master. Tip #2: roc is very helpful. But my takeaway is that it’s well worth the trouble. It is a game changer for debugging.
Anyways, once you’re in
rr replay and have hit your crasher or whatever execution path you’re interested in, and you want to go beyond that
NS_ProcessNextEvent, here is what you can do:
(rr) break nsEventQueue.cpp:60
(Adjust the line number to match wherever the
*aResult = mHead->mEvents[mOffsetHead++]; line is in your tree).
(rr) watch -l mHead->mEvents[mOffsetHead]
And there you are, you just found where the exact event that triggered the executed code you were looking at was put on the event queue. (assuming there isn’t a nested event loop processed during the first
Rinse and repeat.