GNOME Bugzilla – Bug 160132
StatusIcon gives error when panel killed
Last modified: 2007-02-16 05:40:43 UTC
I'm attaching a test case which includes a wrapper I have made based on other gtkmm widgets. Compile this, run the program, switch to another terminal and run "pkill gnome-panel". I get this in the terminal that runs the test program: (test:27758): Gdk-WARNING **: GdkWindow 0x4800003 unexpectedly destroyed Gdk-ERROR **: The program 'test' received an X Window System error. This probably reflects a bug in the program. The error was 'BadWindow (invalid Window parameter)'. (Details: serial 223 error_code 3 request_code 18 minor_code 0) (Note to programmers: normally, X errors are reported asynchronously; that is, you will receive the error a while after causing it. To debug your program, run it with the --sync command line option to change this behavior. You can then get a meaningful backtrace from your debugger if you break on the gdk_x_error() function.) aborting... Trace/breakpoint trap
Created attachment 34377 [details] Test case
The attachment is a .tar.gz
Debugging with --g-fatal-warnings gives this backtrace: (gdb) bt
+ Trace 53029
The way C code avoids this problem is demonstrated in Gossip and Rhythmbox. Check out how gossip does it here: http://cvs.gnome.org/viewcvs/gossip/src/gossip-app.c?rev=1.138&view=auto When the tray icon is created (app_tray_create), they connect to the "destroy" signal and call app_tray_destroy_cb when the widget is destroyed. I'm not sure if this is possible with Gtkmm. It may take some tweaking.
Created attachment 34382 [details] egg2.tar.gz Here is a slightly simplified test case (I removed the Image, which has the disadvantage that it's now invisible), with some extra debugging stuff. However, none of the new warnings seems to appear before the error. I'd like to see a real test case of this in C, to prove that the suggested use of destroy really has the desired affect.
Created attachment 34406 [details] egg-c.tar.gz A C test case demonstrating what rhythmbox and gossip do.
When I run that test case, I get the same warning, though not all of the text: murrayc@murrayc_debian:~/tests/egg-c$ ./test (test:14643): Gdk-WARNING **: GdkWindow 0x3200003 unexpectedly destroyed The "destroy" signal handler does not seem to make any difference - I tried commenting it out. Do you see something different? However, I ran the C++ test case in GNOME 2.9 (FC3), and this is GNOME 2.8 (debian).
The warning will be there no matter whether you're in C or C++. I was talking to Bastian Nocera and he said that is supposed to happen. The thing the C example shows is how they actually make the tray icon re-appear.
Here is the backtrace when the "destroy" signal handler is called: (gdb) run Starting program: /home/murrayc/tests/egg-c/test (test:15099): Gdk-WARNING **: GdkWindow 0x3800003 unexpectedly destroyed Breakpoint 1, 0x0804952a in tray_destroyed () (gdb) bt
+ Trace 53085
We need to a) Stop it being destroyed/disposed. This should happen already. b) Find some other signal/vfunc that is fired at the same time. Then, we need to reshow it or reinitialize somehow, but not recreate it.
I think that the "event" that gtk_main_do_event() is responding to is GTK_EVENT_DESTROY: 1524 case GDK_DESTROY: 1525 /* Unexpected GDK_DESTROY from the outside, ignore for 1526 * child windows, handle like a GDK_DELETE for toplevels 1527 */ Maybe we can handle that. I think that GDK_DELETE is the same as signal_delete_event. I don't know how we could stop gtk_main_do_event() from handling GDK_DESTROY, but maybe we do that already for delete_event for normal containers.
This happens also with Gtk::StatusIcon in gtkmm 2.9: (gdb) run Starting program: /home/murrayc/cvs/gnome214/branches/HEAD/gtkmm/examples/book/statusicon/.libs/lt-example (lt-example:6596): Gdk-WARNING **: GdkWindow 0x3000003 unexpectedly destroyed Gdk-ERROR **: The program 'lt-example' received an X Window System error. This probably reflects a bug in the program. The error was 'BadWindow (invalid Window parameter)'. (Details: serial 1391 error_code 3 request_code 18 minor_code 0) (Note to programmers: normally, X errors are reported asynchronously; that is, you will receive the error a while after causing it. To debug your program, run it with the --sync command line option to change this behavior. You can then get a meaningful backtrace from your debugger if you break on the gdk_x_error() function.) aborting... Program received signal SIGTRAP, Trace/breakpoint trap. IA__g_logv (log_domain=<value optimized out>, log_level=G_LOG_LEVEL_ERROR, format=0xb792a11f "%s", args1=0xbfee2f4c "\uffff\uffff\020\b\003") at gmessages.c:503 503 g_private_set (g_log_depth, GUINT_TO_POINTER (depth)); Current language: auto; currently c (gdb) bt
+ Trace 64630
Backtrace with --g-fatal-warnings: 0 IA__g_logv (log_domain=<value optimized out>, log_level=G_LOG_LEVEL_WARNING, format=0xb7873d08 "GdkWindow %#lx unexpectedly destroyed", args1=0xbfb2a66c "\003") at gmessages.c:503
+ Trace 64631
Apparently GtkStatusIcon is meant to handle this automatically, but here is a C test case that shows the problem. Start the test case then kill the panel to see the warning and crash the test case.
Created attachment 56031 [details] statusicon_test.c
teststatusicon.c from gtk+/tests survives it just fine, when I run it in testtray from libegg/libegg/tray, and kill the tray. The one thing that goes wrong is that the tray icon becomes a visible toplevel window in that case. It should remain hidden. Regarding this bug, you need to figure out in what way the panel systray behaves differently from testtray
CCing Davyd in case he has insight.
I'm not sure why panel maintainers are not cc'ed here :-) So, the notification area applet uses eggtraymanager.c, without any local modification. I don't know about testtray, but I suppose it uses this too. I'll try to look at it.
Matthias, when you say "teststatusicon.c from gtk+/tests survives it just fine, when I run it in testtray from libegg/libegg/tray, and kill the tray.", do you mean "when I ^C testtray" or "when I click testtray's close button"? It works fine for me if I close testtray gently, but if I ^C it, I get a BadWindow error from teststatusicon every time. That's fixed by the gtkplug-x11.c patch below. With that patch, it doesn't get immediately killed when the tray dies, but it doesn't notice that its widgets have been destroyed either, and keeps referring to them, spewing errors, and presumably dying eventually. The gtktrayicon-x11.c patch fixes that, by stopping the destroy_event and forcing the trayicon and its children to re-realize their destroyed windows. With both of those patches, teststatusicon can survive any number of clean and unclean testtray/notification area exits. The gdkwindow-x11.c part of the diff is an additional fix needed for tray icons that do certain kinds of painting (qv bug 150726). That and the plug patch could be useful in gtk 2.8 too.
Created attachment 61397 [details] [review] gtk patches
Created attachment 61398 [details] [review] corresponding eggtrayicon patch (This depends on the gtkplug-x11.c patch from attachment 61397 [details] [review].)
This is primarily a gtk bug at this point (see comment #18).
The gtkplug part makes sense. Why do you need to wrap _gdk_x11_drawable_finish() with an error trap in _gdk_windowing_window_destroy()? Does the X server actually associate a Picture with the drawable passed to XRenderCreatePicture() - and is the Picture already destroyed in the foreign case?
We have XFIXES support in GTK+ now right? Dan - are you testing with older X? That could explain the discrepancy. (Note that *all* you can do without the XFIXES extension is make race conditions less likely. That is, make things more or less recover in the case where GTK+ isn't doing anything when it's window is destroyed.)
Federico: the call to XRenderFreePicture in _gdk_x11_drawable_finish gets an error. (I forget the exact error, but it seemed to be of the "that resource doesn't exist any more" variety.) Owen: this is with xorg-x11 6.9.0.
ah... the XFIXES fix is in the socket code, not the plug code, and I was testing the 2.10 teststatusicon against a gtk-2.8-linked testtray. (There's still at least one problem somewhere that Matthias mentioned, that the icon became a visible toplevel window instead of staying hidden. I'll look into that.)
Hmm, this all works just fine for me now, the status icons even stay invisible, if the panel is killed, then reembed when a new panel is started. Do you still think we need any gtk changes, Dan ?
I can still reproduce the issue from comment 25 with both testtray and the panel's notification area by killing test-tray/gnome-panel. My patch in 340110 fixes the problem for me.
*** Bug 388597 has been marked as a duplicate of this bug. ***
Since the patch in bug 340110 has been committed, I assume this is fixed