dale@amiga.UUCP (Dale Luck) (08/18/88)
Did anyone else try fixing the _XReadEvents bug that I found in the same way I tried? By moving the NULL test to the top of the loop instead of at the bottom? This is the original bug report, I have a some more observations later after the bug report: ------------------------------------------------------------------- VERSION: X11 release 2 CLIENT MACHINE: amiga 2000 CLIENT OPERATING SYSTEM: amigados V1.3 DISPLAY: amiga 640x400 monochrome SYNOPSIS: _XReadEvents can block unnecesarrily DESCRIPTION: _XReadEvents first calls _XFlush. If _XFlush blocks on call to write it will call _XWaitForWritable. This routine reads packets until it can finally write something out. When _XWaitForWritable finally can write on the socket it returns and _XFlush returns to _XReadEvents. _XReadEvents then drops into a loop looking for something to read. If there are no more packets to be read it will block waiting for another packet, yet _XWaitForWritable may have read them all and already Queued them up for processing. REPEAT-BY: Run xcalc and let it start up by itself. Notice it does not complete the calculator text on the buttons until the X-cursor enters the calculator region when the server sends another event the the calculator process. FIX: The fix is to just move the while (dpy->head) to the top of the loop instead of the bottom in _XReadEvents. The following is a diff file for XlibInt.c 129c129 < while (dpy->head == NULL) { ***** new code ***** --- > do { ***** old code ***** 154c154 < } ***** new code ***** --- > } while (dpy->head == NULL); ***** old code ***** Dale Luck amiga!dale -------------------------------------------------------------------- After applying the fix, I no longer get the falsly blocked input, however the client can now easily go into an endless loop somewhere. I don't have the time to look at it thoroughly right now, however I suggest that you back out the proposed fix that I made in the bug report and when a proper fix is invented than we install that. The particular example I had of a client going into an infinate loop was xterm. If I cat'ed /etc/termcap and then quickly moved the cursor in and out of the window or bashed on the keyboard with a few quick keys, it would freeze and the perfmon on the sun3 (my remote host running xterm) would peg user cpu at 100%. Very suspicious. Net traffic had also stopped as writes from the amiga were still getting to the sun3 but not making it into xterm, and there was absolutly no packets being sent from xterm to the amiga. Thanks netstat. Dale Luck amiga!dale
RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (08/18/88)
Date: 18 Aug 88 09:08:56 GMT From: oliveb!amiga!dale@AMES.ARC.NASA.GOV (Dale Luck) Did anyone else try fixing the _XReadEvents bug that I found in the same way I tried? No, we fixed it differently. (The diff below has a few unrelated things included.) I know, I know, we did this a long time ago, and shame on us for not having published it. *** /tmp/,RCSt1a12252 Thu Aug 18 08:10:29 1988 --- lib/X/XlibInt.c Thu Aug 18 08:10:36 1988 *************** *** 2,8 **** /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ #ifndef lint ! static char rcsid[] = "$Header: XlibInt.c,v 11.63 88/02/20 20:21:11 rws Exp $"; #endif /* --- 2,8 ---- /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ #ifndef lint ! static char rcsid[] = "$Header: XlibInt.c,v 11.66 88/05/24 14:34:09 swick Exp $"; #endif /* *************** *** 99,105 **** if (BytesReadable(dpy->fd, (char *) &pend) < 0) (*_XIOErrorFunction)(dpy); if ((len = pend) < sizeof(xReply)) ! return(0); else if (len > BUFSIZE) len = BUFSIZE; len /= sizeof(xReply); --- 99,105 ---- if (BytesReadable(dpy->fd, (char *) &pend) < 0) (*_XIOErrorFunction)(dpy); if ((len = pend) < sizeof(xReply)) ! return(dpy->qlen); /* _XFlush can enqueue events */ else if (len > BUFSIZE) len = BUFSIZE; len /= sizeof(xReply); *************** *** 115,121 **** } /* _XReadEvents - Flush the output queue, ! * then read as many events as possible and enqueue them */ _XReadEvents(dpy) register Display *dpy; --- 115,121 ---- } /* _XReadEvents - Flush the output queue, ! * then read as many events as possible (but at least 1) and enqueue them */ _XReadEvents(dpy) register Display *dpy; *************** *** 124,131 **** --- 124,134 ---- long pend_not_register; /* because can't "&" a register variable */ register long pend; register xEvent *ev; + int qlen = dpy->qlen; _XFlush (dpy); + if (qlen != dpy->qlen) + return; do { /* find out how much data can be read */ if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0) *************** *** 360,366 **** while (newseq < lastseq) { newseq += 0x10000; if (newseq > dpy->request) { ! (void) fprintf(stderr, "sequence lost!\n"); newseq -= 0x10000; break; } --- 363,372 ---- while (newseq < lastseq) { newseq += 0x10000; if (newseq > dpy->request) { ! (void) fprintf (stderr, ! "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", ! newseq, dpy->request, ! (unsigned int) rep->type); newseq -= 0x10000; break; } *************** *** 1011,1017 **** XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", mesg, BUFSIZ); (void) fprintf(stderr, mesg, dpy->request); ! fputs("\n ", stderr); if (event->error_code == BadImplementation) return 0; exit(1); /*NOTREACHED*/ --- 1017,1023 ---- XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", mesg, BUFSIZ); (void) fprintf(stderr, mesg, dpy->request); ! fputs("\n", stderr); if (event->error_code == BadImplementation) return 0; exit(1); /*NOTREACHED*/