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