ado@elsie.UUCP (07/12/88)
VERSION: X11 release 2 CLIENT MACHINE: Sun 3/160 CLIENT OPERATING SYSTEM: Sun UNIX 4.2 Release 3.5 DISPLAY: Sun B&W SYNOPSIS: Clients can terminate abnormally (and erroneously) if the server falls behind. DESCRIPTION: The problem comes about when the socket buffer fills up (at the 4096 character mark on an as-shipped 3.5 system). When this happens, writes to the socket return EMSGSIZE in errno (rather than, for example, EWOULDBLOCK). The function in XlibInt.c that handles output notices the EMSGSIZE error and gets into a loop where it halves the write size each time through. When the write size drops to zero, errno is set to EINVAL and the client punts. REPEAT-BY: Compile and run the attached code from xterm with uwm running, then tap RETURN in the xterm window after you've opened the window. Note the "XIO: Invalid argument" message. (Since the appearance of the message depends on whether the server keeps up with write requests, it's somewhat nondeterministic. If the message does not appear, just tap RETURN a second time, then load up the server with some superfluous windows and try again.) #include "stdio.h" #include "X11/Xlib.h" #define NBPC 8 #define WIDTH 500 #define HEIGHT 500 char data[HEIGHT][WIDTH / NBPC]; main() { Display * display; Window window; GC gc; Visual * visual; int y, x; XImage * ximage; for (y = 0; y < HEIGHT; ++y) for (x = 0; x < sizeof data[y]; ++x) data[y][x] = x + y; display = XOpenDisplay((char *) NULL); XSynchronize(display, 1); window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, WIDTH, HEIGHT, 5, 1, 0); XMapWindow(display, window); (void) getchar(); gc = DefaultGC(display, 0); visual = DefaultVisual(display, 0); ximage = XCreateImage(display, visual, 1, XYBitmap, 0, data, WIDTH, HEIGHT, NBPC, 0); (void) XPutImage(display, window, gc, ximage, 0, 0, 0, 0, WIDTH, HEIGHT); (void) getchar(); return 0; } FIX: I don't know if Sun's 4.0 changes what errno gets set to; in any event, a workaround in the X library is useful for Sun 3.5 binary sites (like ours). We'll assume that if a message of size 1 fails with an EMSGSIZE error, we're on a system that sometimes gives inappropriate EMSGSIZE errors. *** lib/X/XlibInt.c Tue Jul 12 09:59:36 1988 --- lib/X/XlibInt.c Tue Jul 12 09:59:40 1988 *************** *** 310,316 **** --- 310,323 ---- #endif #ifdef EMSGSIZE } else if (errno == EMSGSIZE) { + #ifdef ASWAS todo = todo >> 1; + #else /* !defined ASWAS */ + if (todo == 1) { + _XWaitForWritable(dpy); + todo = total; + } else todo = todo >> 1; + #endif /* !defined ASWAS */ #endif } else { (*_XIOErrorFunction)(dpy); -- ado@ncifcrf.gov ADO is a trademark of Ampex.