Bugzilla – Bug 809
(Expose-)Events not received by MT Xt-application until further events generated
Last modified: 2007-04-07 14:27:50 UTC
I see the following strange behaviour in a multi-threaded Xt-application,
using the OSF/Motif 2.x widget set (but I do not think the bug is related
to Motif): in a callback procedure, I change the pixmaps of some
pushbuttons and their sensitivity state. Sometimes, not all of these
modifications are shown on the screen. I tracked this down to
the fact, that XtNextEvent/XtWaitForSomething block at a time, when
some more Expose events should be in the queue. In fact they are, because
as soon as some further action is done, which generates another event, e.g
pressing a key or moving the pointer so that a LeaveNotify event is generated,
the Expose events are read from the event queue, processed, and everything
My guess is that the XEventsQueued() called in Xt/NextEvent.c:XtAppNextEvent()
do not properly work.
Note: XFlush() does not help, using "-sync" makes it worse.
Note: I tested this on Red Hat Linux 7.2 with XFree86 4.1.0 and on
Tru64 Unix 4.0F with X11R6(?) and on Sun Solaris 8. All show this
problem. I don't run R6.7 yet, but I'm afraid this has not been fixed
Created attachment 430 [details]
test program (requires Motif/OpenMotif)
How to reproduce problem:
- unpack test program, "xmkmf; make"
- run ./mgtest
- it displays 5 control buttons (start, stop, pause, fastforward and
step) and a status line; some buttons are insensitive
- press the "start"-button (leftmost), then the "pause"-button (3rd).
- observe, that sometimes some of the buttons as well as the status
line is not redrawn. This can be "fixed" by pressing a key or moving
the pointer outside the button.
- If you can not see the effect immediately, try the "step"-button
multiple times. If this does not help, kill and restart the program.
- The problem appears more often if run with the "-sync" command
Does it help if you use the libraries (X11/Xt/et al) from fd.o's xlibs module?
That has a lot of threading-related fixes.
I retried with the latest (released) libs from freedesktop.org, in particular:
pascal:~/test/Xt/mgrps(267)> ldd ./mgtest
libXmu.so.6 => /usr/local/freedesktop/lib/libXmu.so.6 (6.2.3)
libXm.so.2 => /usr/X11R6/lib/libXm.so.2 ()
libXt.so.6 => /usr/local/freedesktop/lib/libXt.so.6 (0.1.5)
libSM.so.6 => /usr/local/freedesktop/lib/libSM.so.6 (6.0.3)
libICE.so.6 => /usr/local/freedesktop/lib/libICE.so.6 (6.3.3)
libXp.so.6 => /usr/X11R6/lib/libXp.so.6 ()
libXext.so.6 => /usr/local/freedesktop/lib/libXext.so.6 (6.4.3)
libX11.so.6 => /usr/local/freedesktop/lib/libX11.so.6 (6.2.1)
libpthread.so.0 => /lib/i686/libpthread.so.0 (0x40332000)
libc.so.6 => /lib/i686/libc.so.6 (0x40347000)
libdl.so.2 => /lib/libdl.so.2 (0x40482000)
libXau.so.0 => /usr/local/freedesktop/lib/libXau.so.0 (0.1.1)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
I see the same problem with these libraries. It seemed to be more difficult
to reproduce, but with "-sync", it still happens all the time, and sometimes
I also see the problem without "-sync". I hope it's not a bug in Motif ;-)
OK, I spend some further time analyzing what's going on here. Two threads are
involved, one (lets call it the "Xt loop" thread) does an XtAppMainLoop(), the
other one ("playback") occasionally does some Xlib calls (via XtSetValues/
XtManageChild etc, but I think this does not matter).
When the problems shows up, the following has happened:
The Xt loop thread sits in select(), called from _XtWaitForSomething(), waiting
for input from the X display connection.
The playback thread at the same time is processing Xlib calls, and reads replies
from the X server (_XReply), and also calls _XWaitForReadable multiple times.
The select() system call called from _XWaitForReadable returns, because some
data from the X server is available. While processing the replies, also some
events are read and put into the display's event list.
Unfortunately, the select() call of the Xt loop thread does NOT return while the
playback thread reads replies and events from the connection. (I've verified
that the two select() calls use the same file descriptor in the read-mask and
the max-fd parameter.)
So, finally some events are queued on the dpy's event list, but the Xt loop
thread still waits via select(), and won't process these, until
_XtWaitForSomething will eventually return, for example, if another event
(like key/button press) occurs. (Of course, the playback thread never tries
to process X events.)
Now, I'm stuck. I'm afraid it is undefined whether select() called from
multiple threads will return in one, several or all threads if input becomes
available. Correct? And then it seems to be difficult to fix this
synchronization problem between Xlib and Xt's XtWaitForSomething ...
Any (helpful ;-) comments?
Sorry about the phenomenal bug spam, guys. Adding xorg-team@ to the QA contact so bugs don't get lost in future.
indeed, the behaviour of select in this (rather nasty) case is not guaranteed. you're going to have to pull all the events out in one thread only and pass them along via ipc.