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)