Case Closed (was Re: Help with fixing x2x...)
Thomas Chadwick
j_tetazoo@hotmail.com
Thu Jul 25 13:20:00 GMT 2002
Well, I figured it out. The buggy behavior was indeed due to a bogus value
of nfds. After poking around in the xfree86 source, I came across
xc/lib/Xt/Display.c, which manipulates its own nfds variable in much the
same way as x2x.
In short, changing this:
/* set up for select */
nfds = getdtablesize();
fdset = (fd_set *)malloc(sizeof(fd_set));
fromConn = XConnectionNumber(fromDpy);
toConn = XConnectionNumber(toDpy);
To this:
/* set up for select */
fdset = (fd_set *)malloc(sizeof(fd_set));
fromConn = XConnectionNumber(fromDpy);
toConn = XConnectionNumber(toDpy);
nfds = MAX(fromConn, toConn) + 1;
Does the trick. However, before I repackage it for Cygwin Setup, I'll
probably apply many (if not all) of Harold's suggestions as well.
Thanks, everyone!
>From: Harold L Hunt II <huntharo@msu.edu>
>Reply-To: cygwin-xfree@cygwin.com
>To: cygwin-xfree@cygwin.com
>Subject: Re: Help with fixing x2x...
>Date: Wed, 24 Jul 2002 15:17:52 -0400
>
>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
>>
>
>
_________________________________________________________________
Chat with friends online, try MSN Messenger: http://messenger.msn.com
More information about the Cygwin-xfree
mailing list