[comp.windows.x] monopolizing the server???

ama@alliant.alliant.com (Alan Amaral) (05/25/91)

I've implemented a shared memory interface between Xlib and the server.
Nothing special so far, except that I've noticed that very active shared
memory clients (ico, plaid, etc.) can easily monopolize the server,
excluding, say, the window manager for LONG periods of time.  My
ReadRequestfromClient is modeled closely after the sample code, especially
all the conditions for changing isItTimeToYield to TRUE, but it doesn't seem
to help.

Looking at the code (Dispatch, WaitForSomething, ReadRequestFromClient) it
looks like it's EASY to monopolize the server if your connection is fast
enough because it doesn't seem to be doing what it should.

In io.c (ReadRequestFromClient) the code looks like this:

        if (gotnow >= needed + request_length(request, client))
            BITSET(ClientsWithInput, fd);
	    .
	    .
	    .
    if (++timesThisConnection >= MAX_TIMES_PER)
	YieldControl();

If you've processed the max (10) requests for this client then go check for
other clients.  If other clients have requests buffered then those requests
get processed.  Ok, I'll concede that much.  If there ARE NOT any requests
from other clients else then WaitForSomething gets called again.
Unfortunately, WaitForSomething checks for ANY client having stuff buffered,
and in the case of a fast application which almost always buffers more than
10 requests at a time (i.e. plaid, ico) will resume processing THAT client
BEFORE it will check for input for any other client because it set the
appropriate bit in the ClientsWithInput vector...   So as long as
ReadRequestFromClient keeps a single request in the input buffers you will
NEVER do the crucial select to look for other input.  This seems to be the
case for ANY kind of connection, if the code looks like the sample code.

Am I missing something here?  I want to fix this in my code, and I have a
couple of ways to do it, but I don't want to introduce any kludges if I'm
just misunderstanding the problem and there is a "proper" fix.

john@acorn.co.uk (John Bowler) (06/04/91)

In article <4713@alliant.Alliant.COM> ama@alliant.alliant.com (Alan Amaral) writes:
>Looking at the code (Dispatch, WaitForSomething, ReadRequestFromClient) it
>looks like it's EASY to monopolize the server if your connection is fast
>enough because it doesn't seem to be doing what it should.
>
>[... some explanation deleted ...]
>
>If you've processed the max (10) requests for this client then go check for
>other clients.  If other clients have requests buffered then those requests
>get processed.  Ok, I'll concede that much.  If there ARE NOT any requests
>from other clients else then WaitForSomething gets called again.
>Unfortunately, WaitForSomething checks for ANY client having stuff buffered,
>and in the case of a fast application which almost always buffers more than
>10 requests at a time (i.e. plaid, ico) will resume processing THAT client
>BEFORE it will check for input for any other client because it set the
>appropriate bit in the ClientsWithInput vector...

Dead right.  Its been like this since at least R3, I think it was in R2 too.
(I was sure I reported a bug... but I may have just filed it for later
reporting :-(.

If you fix WaitForSomething plaid can no longer degrade input response in
the way you describe.  Several fixes are possible - you have to decide on
the correct semantics of the calls to the Block and Wakeup Handlers and, if
supporting XTESTEXT1 whether to call XTestProcessInputAction; I only call
either if the select can block.  Whether or not these are called
WaitForSomething *always* polls the various connections for activity or for
new connections whenever it is called.

John Bowler (jbowler@acorn.co.uk)