[comp.windows.x] FIXES FOR: xlsfonts does, sort of, xterm doesn't

lmjm@doc.imperial.ac.UK (04/11/89)

I too had xterm occasionally keeling over and xlsfonts not replying
with the full list.  Here are the patches which worked for me, I
posted both to xbugs but since it seems to be a manufacturer specific
thing as to wether you have these problems I guess these patches won't
become standard.

The problems seem to be in how sockets (and in particular unix domain
sockets) are implemented.

Please read the comments below.

Hope these help.

From lmjm@doc.ic.ac.uk Fri Jan 27 22:24:15 1989
From: Lee McLoughlin <lmjm@doc.ic.ac.uk>
Date: Fri, 13 Jan 89 22:40:10 GMT
To: xbugs <@nss.css.ucl.ac.uk:xbugs@expo.lcs.mit.edu>
Cc: lmjm@doc.ic.ac.uk
Subject: X.V11R3 bug report 

			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu




VERSION:
    R3

CLIENT MACHINE and OPERATING SYSTEM:
    HLH Clipper Orion running 4.2 BSD

DISPLAY:
    HLH StarPoint
    [Digital QVSS, Sun CG4, HP Topcat, IBM APA16, Apollo 4 plane, ...]

WINDOW MANAGER:
    awm

AREA:
    Xlib (xterm)

SYNOPSIS:
    xterm using a Unix domain socket will quit unexpectedly when
    listing long files.

DESCRIPTION:
    Xlib in XlibInt.c in the routine _XSend() somehow ends up passing a
    0 as the third arg to WritevToServer().  This causes the writev() then
    to fail with an EINVAL error.  After detailed tracing of the code
    I have no idea why this occurs.  It only happens with Unix domain
    sockets - not with TCP sockets.

REPEAT BY:
    setenv DISPLAY unix:0
    xterm
      in the xterm window turn on jump scroll
      then do "cat /etc/termcap"

    after 3 pages or so xterm will quit with an error message of:
	xterm: invalid arg

SAMPLE FIX:
    Since it can never reach the WritevToServer() without having
    something to write and that would have to be in iov I just ensure
    i is at least one.

*** XlibInt.c.orig	Thu Jan 12 23:19:54 1989
--- XlibInt.c	Fri Jan 13 22:39:40 1989
***************
*** 495,500 ****
--- 495,505 ----
  	    InsertIOV(pad, padlength[size & 3])
      
  	    errno = 0;
+ 
+ 	    /* Always using at least iov[ 0 ] */
+ 	    if (i == 0)
+ 		    i = 1;
+ 
  	    if ((len = WritevToServer(dpy->fd, iov, i)) >= 0) {
  		skip += len;
  		total -= len;

------------------------------------------------------------------------------
From lmjm@doc.ic.ac.uk Fri Jan 27 22:27:06 1989
From: Lee McLoughlin <lmjm@doc.ic.ac.uk>
Date: Mon, 16 Jan 89 20:55:55 GMT
To: xbugs <@nss.cs.ucl.ac.uk:xbugs@expo.lcs.mit.edu>
Cc: lmjm@doc.ic.ac.uk
Subject: X.V11R3 bug report 

			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu




VERSION:
    R3

CLIENT MACHINE and OPERATING SYSTEM:
    HLH Clipper Orion running 4.2 BSD

DISPLAY:
    HLH StarPoint
    [Digital QVSS, Sun CG4, HP Topcat, IBM APA16, Apollo 4 plane, ...]

WINDOW MANAGER:
    awm

AREA:
    X server 

SYNOPSIS:
    The server fails to write any message greater than 8K back to the client.

DESCRIPTION:
    Under 4.2 BSD the max size of a message you can send on a pipe is
    8K (at least on the few 4.2 BSD's I could find).  In
    server/os/4.2bsd/io.c FlushClient() allows blocks of any size to
    be written.

REPEAT BY:
    With all the core fonts available try:
	xlsfonts
    This fails with
Connection # 3 to server broken.
XIO: Broken pipe

SAMPLE FIX:
    I've made the code #ifdef'd hlh - the machine I wrote it for.  It should
    really be for any machine with a socket message size limit but I couldn't
    find any suitable #define and didn't feel up to adding one - its been
    a long day.

*** io.c.old	Mon Jan 16 18:19:18 1989
--- io.c	Mon Jan 16 20:52:39 1989
***************
*** 314,353 ****
      int connection = oc->fd,
      	total, n, i, notWritten, written,
  	iovCnt = 0;
      struct iovec iov[3];
      char padBuffer[3];
  
      total = 0;
      if (oc->count)
      {
! 	total += iov[iovCnt].iov_len = oc->count;
! 	iov[iovCnt++].iov_base = (caddr_t)oc->buf;
          /* Notice that padding isn't needed for oc->buf since
             it is alreay padded by WriteToClient */
      }
      if (extraCount)
      {
! 	total += iov[iovCnt].iov_len = extraCount;
! 	iov[iovCnt++].iov_base = extraBuf;
  	if (extraCount & 3)
  	{
! 	    total += iov[iovCnt].iov_len = padlength[extraCount & 3];
! 	    iov[iovCnt++].iov_base = padBuffer;
  	}
      }
  
      notWritten = total;
      while ((n = writev (connection, iov, iovCnt)) != notWritten)
      {
  #ifdef hpux
  	if (n == -1 && errno == EMSGSIZE)
  	    n = swWritev (connection, iov, 2);
  #endif
          if (n > 0) 
          {
  	    notWritten -= n;
  	    for (i = 0; i < iovCnt; i++)
              {
  		if (n > iov[i].iov_len)
  		{
  		    n -= iov[i].iov_len;
--- 314,406 ----
      int connection = oc->fd,
      	total, n, i, notWritten, written,
  	iovCnt = 0;
+ #define _AddToIov( bytes, len ) \
+     total += iov[iovCnt].iov_len = (len); \
+     iov[iovCnt++].iov_base = (caddr_t)(bytes);
+ #ifndef hlh
      struct iovec iov[3];
+ #define AddToIov(bytes, len) _AddToIov(bytes, len)
+ #else
+     int iovs;
+     struct iovec iov[100]; /* Enough to avoid the need for dynamic allocation */
+ #define MAX_MSG 8192 /* Max size of a single iov to writev */
+ #define AddToIov( bytes, len ) \
+     { \
+ 	    char *buf = bytes; \
+ 	    int towrite = len; \
+ 	    while( towrite > MAX_MSG ){ \
+ 		    _AddToIov( buf, MAX_MSG ); \
+ 		    towrite -= MAX_MSG; \
+ 		    buf += MAX_MSG; \
+ 	    } \
+ 	    _AddToIov( buf, towrite ); \
+     }
+ #endif
      char padBuffer[3];
  
      total = 0;
      if (oc->count)
      {
! 	AddToIov( oc->buf, oc->count );
          /* Notice that padding isn't needed for oc->buf since
             it is alreay padded by WriteToClient */
      }
      if (extraCount)
      {
! 	AddToIov( extraBuf, extraCount );
  	if (extraCount & 3)
  	{
! 	    AddToIov( padBuffer, padlength[extraCount & 3] );
  	}
      }
  
      notWritten = total;
+ #ifndef hlh
      while ((n = writev (connection, iov, iovCnt)) != notWritten)
+ #else
+     iovs = iovCnt;
+     while ((n = writev (connection, iov, iovs)) != notWritten)
+ #endif
      {
  #ifdef hpux
  	if (n == -1 && errno == EMSGSIZE)
  	    n = swWritev (connection, iov, 2);
  #endif
+ #ifdef hlh
+ 	if (n == -1 && errno == EMSGSIZE){
+ 		/* Too large a lump to write.
+ 		 * try with a fewer iov's.
+ 		 */
+ 		int siz = 0;
+ 		struct iovec *ip;
+ 
+ 		/* How many iov's are less than the max? */
+ 		iovs = 0;
+ 		ip = &iov[0];
+ 		while( (siz + ip->iov_len) <= MAX_MSG ){
+ 			siz += ip->iov_len;
+ 			ip++;
+ 			iovs++;
+ 		}
+ 		continue;
+ 	}
+ 	else {
+ 		/* Once its succeeded then try to write the rest - the
+ 		 * code in the if statement below should prevent iov's from
+ 		 * being resent */
+ 		iovs = iovCnt;
+ 	}
+ #endif
          if (n > 0) 
          {
  	    notWritten -= n;
  	    for (i = 0; i < iovCnt; i++)
              {
+ #ifdef hlh
+ 		/* ignore buffers that have been written already */
+ 		if (iov[i].iov_len == 0 )
+ 			continue;
+ #endif
  		if (n > iov[i].iov_len)
  		{
  		    n -= iov[i].iov_len;

--
Lee McLoughlin			01 589 5111 X 5028
Department of Computing,Imperial College,180 Queens Gate,London SW7 2BZ, UK
Janet: lmjm@uk.ac.ic.doc	Uucp:  lmjm@icdoc.UUCP, ukc!icdoc!lmjm
DARPA: lmjm@doc.ic.ac.uk (or lmjm%uk.ac.ic.doc@nss.cs.ucl.ac.uk)