Case Closed (was Re: Help with fixing x2x...)
Harold L Hunt II
huntharo@msu.edu
Thu Jul 25 13:45:00 GMT 2002
Thomas,
Excellent.
In xwinclip I calculate the maximum socket number just like you are doing:
/* Find max of our file descriptors */
iMaxDescriptor = max (fdMessageQueue, iConnectionNumber) + 1;
At least it is fixed now.
Harold
Thomas Chadwick wrote:
> 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