Going beyond NS_ProcessNextEvent
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 (rr) reverse-continue
(Adjust the line number to match wherever the *aResult = mHead->mEvents[mOffsetHead++];
line is in your tree).
(rr) disable (rr) watch -l mHead->mEvents[mOffsetHead] (rr) reverse-continue (rr) disable
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 reverse-continue
)
Rinse and repeat.
2016-02-05 07:19:41+0900
Responses are currently closed, but you can trackback from your own site.
2016-02-21 01:56:33+0900
I’ve had to debug around something similar in a codebase I worked with. If you can make a debug build that includes a bit of extra code to add a caller stack trace to every event, that also helps a lot.