Path: utzoo!attcan!uunet!cs.utexas.edu!usc!bloom-beacon!doc.imperial.ac.UK!lmjm From: lmjm@doc.imperial.ac.UK Newsgroups: comp.windows.x Subject: re: XIO errors again Message-ID: <8907202157.aa06336@tgould.doc.ic.ac.uk> Date: 20 Jul 89 21:53:18 GMT References: <579@elan.elan.com> Sender: daemon@bloom-beacon.MIT.EDU Organization: The Internet Lines: 258 I too was plauged by "XIO error" problems. Here are the pair of reports I sent out ages out containing patches that seem to fix most of these problems. One fixes some weird case where writev is asked to write 0 bytes the other makes sure that when the server uses writev to send a client its gives writev manageable chunks. Hope these are useful. Lee ------------------------------------------------------------------------- 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 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; ------------------------------------------------------------------------- VERSION: R3 CLIENT MACHINE and OPERATING SYSTEM: HLH Clipper Orion running 4.2 BSD DISPLAY: HLH StarPoint 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 phone: 01 589 5111 X 5028 fax: 01 581 8024 Department of Computing,Imperial College,180 Queens Gate,London SW7 2BZ, UK Janet: lmjm@uk.ac.ic.doc Uucp: lmjm@icdoc.UUCP (or ..!ukc!icdoc!lmjm) DARPA: lmjm@doc.ic.ac.uk (or lmjm%uk.ac.ic.doc@nsfnet-relay.ac.uk)