Tuesday, February 19, 2008

stuck inside of mozil' with the memphis blues again

Been trying to figure out why the heck I get a segfault when trying to call OnNotificationAreaClick when the tray icon is clicked. The GTK signal callback gets the correct pointer, but GDB doesn't really help with telling what it actually points to. Not even in ShowIcon, where aListener seems to point to something entirely unrelated:

Breakpoint 1, nsDesktopEnvironment::ShowIcon (this=0x858d2c0,
aIconId=@0xbfd9ad28, aImageURI=0x858bde0, aListener=0x858d738)

(gdb) x aListener
0x858d738: 0xb7a09ac8
(gdb) p aListener
$7 = (struct nsINotificationAreaListener *) 0x858d738
(gdb) x/wa *(void**)aListener
0xb7a0bac8 <_ZTVN10gfxTextRun16PropertyProviderE+627120>: 0xb7715d4c
At least using this guide. It probably has to do with how nsINotificationAreaListener is defined and actually used (being QI'd through XPConnect, as the WebRunner object is the one implementing the interface). But I don't grok XPCOM enough to actually say that with any degree of confidence. Calling the OnNotification... method in ShowIcon does work at least.
Then we come to the callback which GTK calls when the icon is clicked:
Breakpoint 2, notify_cb (icon=0x8545120, data=0x858d738)
(gdb) p data
$9 = (gpointer) 0x858d738
(gdb) x data
0x858d738: 0x54746573
(gdb) x/wa *(void**)data
0x54746573: Cannot access memory at address 0x54746573
(gdb) x/s data
0x858d738: "setTitle"
The memory access thing is probably what makes it segfault. And yeah, that string is what happens to be there every single time I run it through the debugger. The callback's defined thusly:
void notify_cb(GtkStatusIcon *icon,
gpointer data) {
nsCOMPtr<nsINotificationAreaListener> listen;
listen = (nsINotificationAreaListener *)data;
listen->OnNotificationAreaClick(0,2);
}
And hooked up like so:
g_signal_connect(mStatusIcon, "activate", G_CALLBACK(notify_cb),
(gpointer)aListener);
in ShowIcon (mStatusIcon is the GtkStatusIcon pointer, gpointer is typedef-ed as void*). Totally imitating the logic in the Windows tray code (where the pointer is stored as a property attached to the listener window that detects clicks on the icon). The actual segfault happens when the nsCOMPtr tries to AddRef the pointee in the assignment operator.

I would add a watch to see what actually happens to change the pointer, but since it's a multi-threaded app, GDB kills the watch as soon as the thread it's defined in gets preempted. So, what, Valgrind? Mommy, the big-boy pants are coming on... (Or I'm just doing something stupid that I'm overlooking.)

No comments: