GNOME Bugzilla – Bug 552041
Windows' System Menu from taskbar is buggy
Last modified: 2011-11-08 19:07:48 UTC
Please describe the problem: Right clicking a GTK window's entry in the Windows Taskbar to bring up the System Menu causes a similar bug to 539164, and is almost assuredly related. Any drawing in the window freezes, but unlinke 539164, the following warnings also appear in the console: (gtk-demo.exe:3708): GLib-WARNING **: g_main_context_prepare() called recursivel y from within a source's check() or prepare() member. (gtk-demo.exe:3708): GLib-WARNING **: g_main_context_check() called recursively from within a source's check() or prepare() member. These pair of warnings print repeatedly while the menu is up. This is not a crasher, the application behaves normally once the menu is dismissed, same as 539164. Steps to reproduce: 1. Run gtk-demo.exe 2. Open the pixbufs demo. (Or the Images demo, the behavior is the same.) 3. Right click "Pixbufs" in the taskbar. Actual results: Animation freezes and GLib-WARNINGS print to the console. Expected results: The animation should continue and no warnings should appear. Bobviously. Does this happen every time? Yes. Other information: I don't mean to seem ungrateful by filing a bug about the same thing as 539164. But this is a little corner case that got through. I'll get a dev environment on this stupid windows box one of these days!
Eek! Nice catch. Note that if one just right-clicks on the taskbar entry of gtk-demo in its initial state with no demo running one also gets warnings as long as the right-click menu is up.
I found this bug in: gtk+-bundle_2.14.4-20081018_win32.zip gtk+-bundle_2.14.3-20081017_win32.zip gtk+-bundle_2.14.2-20080924_win32.zip It's in gtk-demo. It's in empty (and any) window I run from Gtk2::Perl. It's probably in any win32 window with gtk_main() created without special jumps around.
No longer seeing this after upgrade to 2.16.0.
I do see the same problem with 2.16.0, trying exactly what the initial description says.
(In reply to comment #4) > I do see the same problem with 2.16.0, trying exactly what the initial > description says. > I am terribly embarrassed to say that I tried to reproduce by right clicking the titlebar, forgetting that the bug is triggered by the taskbar instead. Sorry for the noise and wasted time. (In the future I will read my own reports.)
I also see this problem when I right-click the taskbar in my pygtk application. I'm using pygtk-2.16.0 with the gtk2 2.16.6 runtime files. I get the following warnings: C:\myui.py:183: Warning: g_main_context_prepare() called recursively from within a source's check() or prepare() member. C:\myui.py:183: Warning: g_main_context_check() called recursively from within a source's check() or prepare() member. Line 183 is my call to gtk.main(). The program locks up while the right-click menu is open.
I also see this problem,platform is windows XP: (gtk-demo.exe:6584): GLib-WARNING **: g_main_context_prepare() called recursively from within a source's check() or prepare() member. (gtk-demo.exe:6584): GLib-WARNING **: g_main_context_check() called recursively from within a source's check() or prepare() member. (gtk-demo.exe:6584): GLib-WARNING **: g_main_context_prepare() called recursively from within a source's check() or prepare() member. (gtk-demo.exe:6584): GLib-WARNING **: g_main_context_check() called recursively from within a source's check() or prepare() member. Is this gonna be fixed?
Allan, what vesion of GTK+ are you using?
(In reply to comment #8) > Allan, what vesion of GTK+ are you using? It's the latest version: http://ftp.gnome.org/pub/GNOME/binaries/win32/gtk+/2.20/gtk+-bundle_2.20.0-20100406_win32.zip It seems this problem doesn't exist for some windows XP users,but unfortunately it does exist for me :(
Has anyone managed to find a workaround for this that can be implemented in the program source code?
I've been tracing this with a simple test program[1], using gtk+-bundle_2.20.0-20100406_win32, a recompiled gtk+-2.20.0 and glib-2.24.0 with debug symbols and eventually found a way to "see" where this warning is produced... Every time modal_timer_proc gets executed when right-clicking the taskbar entry resulted in the flood of warnings. I've run test.exe through gdb with the attached script.txt as follows: G_DEBUG="fatal_warnings" GDK_DEBUG=EVENTS gdb --command script.txt test.exe. The moment the task bar entry appears, I've right-clicked it. On my XP machine the 26th time g_main_context_prepare gets executed results in a warning (not always, but reliably enough to hit the right spot in a couple of tries...) Stepping through the 25th hit revealed the problem: the PeekMessageW call in gdk_event_prepare seems to release control! See output.txt:181. As the PeekMessageW function gets called with the PM_NOREMOVE parameter, it's only goal is to see if there are messages on the message queue, so we can replace this call with GetQueueStatus (QS_ALLINPUT)[2]. I've done this for all 3 calls to PeekMessageW that get called with PM_NOREMOVE (in gdk_events_pending, gdk_event_prepare and gdk_event_check) and the warnings are gone. Eureka! After that I've tested "Pixbufs" from gtk-demo to verify modal_timer_proc still functions (the animation continues even when right-clicking the title bar or the task bar entry for both the “GTK+ Code Demos” and the “Pixbufs” windows without producing warnings. I've tested with other "in house" PyGTK applications and have not yet encountered any other problems caused by this patch. Note I'm far from an expert on the glib mainloop nor gdk-win32, so did I get it right? [1] attached test.c, compile with gcc -Wall -ggdb test.c -o test `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` [2] http://msdn.microsoft.com/en-us/library/ms644940%28v=VS.85%29.aspx
Created attachment 168191 [details] script.txt
Created attachment 168192 [details] test.c
Created attachment 168193 [details] output.txt
Created attachment 168194 [details] fix_gdk_gsource.patch
Was the patch committed? I'm not experiencing the problem anymore with Gtk 2.22 (32-bit) running on Windows 7 Professional 64-bit.
I don't think anybody ever looked at the patch... A shame, really, it took three weeks of free time to hunt this down :( For the record, the problem continues to exist in gtk+ 2.22 and 2.24 (on windows xp, at least)...
*** Bug 635065 has been marked as a duplicate of this bug. ***
This would likely also fix GLib bug #137968 and what looks like it's duplicate #468910...
I've now applied your patch to my local build of gtk-2-16 and it seems to work. But the only explaination I have is the one given by Tor in bug #137968: """The PeekMessage() calls apparently can cause calls to the window procedure. The calls to PeekMessage(PM_NOREMOVE) in gmain.c and gdkevents-win32.c probabnly should be changed to GetQueueStatus(QS_ALLINPUT) calls instead. as that does less unexpected stuff.""" That looks reasonable and from my current understanding there also should be no problem by "(GetQueueStatus) does not guarantee that a subsequent call to the GetMessage or PeekMessage function will return a message" [1] but I'm a bit uncertain about that. [1] http://msdn.microsoft.com/en-us/library/ms644940%28v=vs.85%29.aspx
(In reply to comment #20) > I've now applied your patch to my local build of gtk-2-16 and it seems to work. > But the only explaination I have is the one given by Tor in bug #137968: > > """The > PeekMessage() calls apparently can cause calls to the window procedure. The > calls to PeekMessage(PM_NOREMOVE) in gmain.c and gdkevents-win32.c probabnly > should be changed to GetQueueStatus(QS_ALLINPUT) calls instead. as that does > less unexpected stuff.""" Yeah, there are more remarks like that to be found on the web but actual real documentation on some of the quirks of PeekMessage seems to be hard to come by these days. My best guess is that we are seeing a ghost of the old 16-bit Windows' cooperative multitasking days, where PeekMessage, GetMessage and Yield released control to allow another application to run (and who knows what else lies hidden within these functions). I'm also distinctly remember once reading a page mentioning any code calling PeekMessage should be prepared to be reentrant safe. Alas my bookmarks are failing me here. > That looks reasonable and from my current understanding there also should be no > problem by "(GetQueueStatus) does not guarantee that a subsequent call to the > GetMessage or PeekMessage function will return a message" [1] but I'm a bit > uncertain about that. > > [1] http://msdn.microsoft.com/en-us/library/ms644940%28v=vs.85%29.aspx Worst case scenario gdk_events_pending, gdk_event_prepare or gdk_event_check will say there's something to do. Then when gdk_event_dispatch is called there's nothing to be done. gdk_event_dispatch already checks for that case so nothing actually happens. I don't think that should be a problem, but that's also from my current understanding of gdk internals... Thanks for your review, Dieter
Ok, I've researched this, and this patch looks very correct. Messages in win32 are either "posted" or "sent". Posted messages are queued on the message queue for the thread, and are then eventually returned by GetMessage or PeekMessage. However, "sent" messages are delivered directly to the window procedure, meaning that if the SendMessage call is in the same thread as the window it will be a direct function call, and if not the message will be queued on the destination thread and will be dispatched immediately to the window procedure the first thing when GetMessage *or* PeekMessage is called (no filtering possible). Here are some relevant links: http://stackoverflow.com/questions/1133507/is-there-a-function-like-peekmessage-that-doesnt-process-messages http://books.google.com/books?id=wYrCitbs5PQC&pg=PT342&lpg=PT342&dq=PeekMessage+nonqueued+messages&source=bl&ots=VpbOhZHZiC&sig=MccIqAUpy_PlnJ6u1L7fFwWepV0&hl=en&ei=hzShTv7TGYP6sgavo_GwBw&sa=X&oi=book_result&ct=result&resnum=3&ved=0CCoQ6AEwAg#v=onepage&q=PeekMessage%20nonqueued%20messages&f=false PeekMessage API func says: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644943%28v=vs.85%29.aspx During this call, the system delivers pending, nonqueued messages, that is, messages sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that matches the specified filter is retrieved. The system may also process internal events. http://msdn.microsoft.com/en-us/library/windows/desktop/ms644927%28v=vs.85%29.aspx Has this part: Note that the receiving thread need not yield control explicitly; calling any of the following functions can cause a thread to yield control implicitly. DialogBox DialogBoxIndirect DialogBoxIndirectParam DialogBoxParam GetMessage MessageBox PeekMessage SendMessage I'm pulling this patch into my gtk-2-24-win32 branch which I hope to merge soon.
Oh, and GetQueueStatus possibly returning early seems safe to me, as look as it doesn't keep doing that after we've called GetMessage, because that might be an infinite loop. I don't think that will happen though.
http://git.gnome.org/browse/gtk+/commit/?h=gtk-2-24&id=12507a7cc2dcbc4f4c85acaafda8596de9364048 This problem has been fixed in our software repository. The fix will go into the next software release. Thank you for your bug report.