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

p.m.o

Responses are currently closed, but you can trackback from your own site.

One Response to “Going beyond NS_ProcessNextEvent”

  1. Simon Rugger Says:

    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.