This is the mail archive of the cygwin-xfree@cygwin.com mailing list for the Cygwin XFree86 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Help with fixing x2x...


Thomas Chadwick wrote:
Hmmm. I tried your suggestion and the behavior has not changed. It's still gobbling up 99% of the CPU. Suspecting that select() is not blocking like it should, I inserted "printf("Hello\n");" just before the select() function call. Now when I run x2x I get a continuous stream of "Hello"s on STDOUT whether or not I'm moving the mouse or typing.

By comparison, I compiled x2x on my AIX workstation, including the "Hello" addition. When I run x2x there, I observe that it only prints "Hello" when I move the mouse or hit a key. This seems to me to be the appropriate behavior.

This little experiment implicates the select() function call itself as being the source of the trouble. Now the question is, is it a problem with how select() is being used (and if so, is the problem at the Xserver or the Xclient end), or is there a problem with the Cygwin implementation of it?

Are you aware of any Xclients which use select() and yet do not exhibit the non-blocking behavior I'm seeing? Perhaps there is a minor tweak required in how it is being called.

Yup, xwinclip uses select () just like x2x does:

http://xfree86.cygwin.com/devel/xwinclip/changelog.html

Just download the tarball for Test06 and look in xwinclip.c/main ()/Line 390.

I think the problem may be with the value that getdtablesize () is returning. To find out, you need to printf the value of nfds, fromConn, and toConn. If nfds isn't at least one larger than the maximum of fromConn and toConn, then you have a problem. You can alternatively replace nfds in the call to select with FD_SETSIZE.

Probably the main problem here, other than if nfds is incorrect, is that the event loop fails to flush all X events before its first call to select (), which is necessary because there may be events stored in local structures already. Also, the manner in which the program determines whether or not events are pending is non-standard and easy to break.

One other thing: the original programmer is malloc'ing fdset and freeing it later. This is entirely unnecessary, fdset should be an automatic variable instead.

I recommend completely replaceing the DoX2X function with the one below. I promise that it will work this time :)

Harold


static void DoX2X(fromDpy, toDpy)
Display *fromDpy;
Display *toDpy;
{
DPYINFO dpyInfo;
fd_set fdset;
int fromConn, toConn;
int iReturn;
Bool fReturn;

/* set up displays */
dpyInfo.fromDpy = fromDpy;
dpyInfo.toDpy = toDpy;
InitDpyInfo (&dpyInfo);
RegisterEventHandlers (&dpyInfo);

/* get file handles for display event pipes */
fromConn = XConnectionNumber(fromDpy);
toConn = XConnectionNumber(toDpy);

/*
* We have to clear any pending events before our
* first call to select, because there may be events
* stored in local structures. Failing to clear these
* events will lead to select failing to operate
* properly. We just set the event flags here so
* that both event loops are entered on the first time
* through the main loop below.
*/
FD_ZERO (&fdset);
FD_SET (fromConn, &fdset);
FD_SET (toConn, &fdSet);

/* Loop forever */
while (True)
{
/* Check for events for From display */
if (FD_ISSET (fromConn, &fdset))
{
/* Process any pending events for From display */
while (XPending (fromDpy))
fReturn = ProcessEvent (fromDpy, &dpyInfo);

/* Check for failure */
if (fReturn) break;
}

/* Check for events for To display */
if (FD_ISSET (toConn, &fdset))
{
/* Process any pending events for To display */
while (XPending (toDpy))
fReturn = ProcessEvent (toDpy, &dpyInfo);

/* Check for failure */
if (fReturn) break;
}

/* Setup the structures for select () */
FD_ZERO(&fdset);
FD_SET(fromConn, &fdSet);
FD_SET(toConn, &fdSet);

/* Wait for events from either screen before looping again */
iReturn = select (FD_SETSIZE, &fdset, NULL, NULL, NULL);
if (iReturn <= 0)
{
printf ("Call to select () failed. Bailing.\n");
break;
}
}
}


From: Harold L Hunt II <huntharo@msu.edu>
To: Thomas Chadwick <j_tetazoo@hotmail.com>
CC: cygwin-xfree@cygwin.com
Subject: Re: Help with fixing x2x...
Date: Tue, 23 Jul 2002 18:58:15 -0400

Thomas,

In x2x, the return value from ProcessEvent which indicates that everything went normally is False, not True. The real intentions for the return value of ProcessEvent can be described by the boolean variable called ``bAbortedDisconnect'' that is returned from ProcessMotionNotify. Much more on that below but for now,

Ohmygodthatisfunny!!!

In the loop, the code does this:

1) Check for an event on fromDpy. XPending returns immediately.

2) Process the event for fromDpy if an event was pending. If we processed an event successfully, continue looping. Else, the ProcessEvent function returned True and we are supposed to shutdown, thus the ``break''.

3) Check for an event on toDpy. XPending returns immediately.

4) Process the event for toDpy if an event was pending. If we processed an event successfully, continue looping. Else, the ProcessEvent function returned True and we are supposed to shutdown, thus the ``break''.

5) Else, if we did not process an event from either screen, wait until one or both o fthe file handles that represent the display event queues becomes ready for reading.

I think that your infinite loop has to do with the fact that XPending returns a count of events ready for reading in fromPending, rather than a boolean value. I think that (!fromPending) had the desired effect on the developer's platform of determining that (fromPending == 0), but that is a highly compiler-dependent assumption on behalf of the original developer.

For clarity, I would rewrite the section as follows (notice the correction in the ``else if''):

====================================================================
while (True) /* FOREVER */
{
/* Save the number of event ready for fromDpy */
fromPending = XPending(fromDpy);

/* Process any events ready for fromDpy */
if (fromPending != 0)
if (ProcessEvent(fromDpy, &dpyInfo)) /* shutdown if True! */
break;

/* Process any events ready for toDpy */
if (XPending(toDpy))
{
if (ProcessEvent(toDpy, &dpyInfo)) /* shutdown if True! */
break;
}
else if (fromPending == 0)
{
/* No events ready for either display. Wait for an event. */
FD_ZERO(fdset);
FD_SET(fromConn, fdset);
FD_SET(toConn, fdset);
select(nfds, fdset, NULL, NULL, NULL);
}
} /* END FOREVER */
====================================================================

Now, for the excitement about the bAbortedDisconnect variable from ProcessMotionNotify:

It looks like the original programmer is using some sort of consistency checking on MotionNotify events to determine that the X server is shutting down. I will have to look into this further, but it looks promising from my initial inspection. This is the final step that I need for xwinclip to function properly on server resets and shutdowns. Needless to say, hopefully I am seeing what I want to see :)

Harold



Thomas Chadwick wrote:

I recently discovered that when I run x2x, the Win2k Task Manager reports that it's using 90-99% of the CPU.

While I have not noticed a slow down in performance when it's running, I'd like to fix it if I can. I've poked around in the source and I don't like the looks of the main loop:

while (True) { /* FOREVER */
if (fromPending = XPending(fromDpy))
if (ProcessEvent(fromDpy, &dpyInfo)) /* done! */
break;

if (XPending(toDpy)) {
if (ProcessEvent(toDpy, &dpyInfo)) /* done! */
break;
} else if (!fromPending) {
FD_ZERO(fdset);
FD_SET(fromConn, fdset);
FD_SET(toConn, fdset);
select(nfds, fdset, NULL, NULL, NULL);
}

It would appear to me that this constant polling for an event to process is what's eating up the CPU cycles.

Not being an X programmer, I'm hoping someone monitoring the list can suggest a way to modify this loop to be less of a CPU hog.

Thanks.


_________________________________________________________________
MSN Photos is the easiest way to share and print your photos: http://photos.msn.com/support/worldwide.aspx




_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]