mouse@LARRY.MCRCIM.MCGILL.EDU (der Mouse) (06/25/89)
I'm seeing a strange problem which appears to be something strange in the guts of Xlib, or (perhaps) my failure to notice something buried somewhere in the Xlib documentation. Preparatory facts: - I wrote my own terminal emulator ("mterm") using bare Xlib. - MIT X11R3 on Sun-3s running release 3.5; bwtwo and cgfour displays. - X is always started via the xinit mechanism. When killing xinit's distinguished client (it's one I wrote expressly for the purpose of being xinit's distinguished client), I will sometimes later see mterms (always on other machines) running in the background soaking up as much cpu as UNIX is willing to give them, clearly in infinite loops, left over from the X session. Taking core dumps (with "kill -STOP" and "gcore") revealed that the infinite loop is in the code that reads from the pty and the X connection. This code looks roughly like this: while (1) { if (XQLength(disp) > 0) { read events and act on them } choose a timeout for the select - see below call select() on the pty and XConnectionNumber(disp) if (the select timed out) { if (the window needs updating) update it if (there might be stuff to flush to the X server) { XSync(disp,False); /* see below */ } continue; } if (select indicates something on the X connection) { XEventsQueued(disp,QueuedAfterReading); continue; } if (select indicates something on the pty) { handle stuff on the pty } } The timeout on the select is chosen based on whether we think the X connection might need flushing and whether the window needs updating. If either one is true, the timeout is zero; otherwise, the timeout is non-zero (depending on other factors), from about half a second to infinity. (The XSync call used to be XFlush, but if I do that there's a race condition involving scrolling that manifests as damaged characters not getting repaired when the window is scrolling rapidly and is partially obscured.) The problem seems to be that I'm stuck in an infinite loop, with select() perpetually indicating the presence of something on the X connection. (For some reason, Xlib never either reads it or notices EOF.) What I've resorted to for now is rather inelegant - I count the number of times I call XEventsQueued, clearing this count each time I actually read an event (in the if at the top of the loop), and if the count goes over 10000, I summarily exit(). (It remains to be seen whether this is a complete solution, but I certainly can't see how it would fail.) All other ways I've come up with involves calling Xlib internal routines directly, which is even more inelegant. :-P (I know, If I were using Xt, the solution would be to give the pty fd to the toolkit as another source of input. But I'm not using Xt.) What's the proper Xlib solution? der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
eric@pyramid.pyramid.com (Eric Bergan) (06/26/89)
In article <8906251323.AA27600@Larry.McRCIM.McGill.EDU> mouse@LARRY.MCRCIM.MCGILL.EDU (der Mouse) writes: >I'm seeing a strange problem which appears to be something strange in >the guts of Xlib, or (perhaps) my failure to notice something buried >somewhere in the Xlib documentation. > >When killing xinit's distinguished client (it's one I wrote expressly >for the purpose of being xinit's distinguished client), I will >sometimes later see mterms (always on other machines) running in the >background soaking up as much cpu as UNIX is willing to give them, >clearly in infinite loops, left over from the X session. > >Taking core dumps (with "kill -STOP" and "gcore") revealed that the >infinite loop is in the code that reads from the pty and the X >connection. This code looks roughly like this: > > while (1) > { if (XQLength(disp) > 0) > { read events and act on them > } > choose a timeout for the select - see below > call select() on the pty and XConnectionNumber(disp) > if (the select timed out) > { if (the window needs updating) update it > if (there might be stuff to flush to the X server) > { XSync(disp,False); /* see below */ > } > continue; > } > if (select indicates something on the X connection) > { XEventsQueued(disp,QueuedAfterReading); > continue; > } > if (select indicates something on the pty) > { handle stuff on the pty > } > } xperfmon seems to suffer from the same problem. The select down in the Xlib is not reacting properly to the EOF and instead, just ends up looping, doing lots of select()'s. The problem may be with any application that tries to do select()s on the same fd's that the Xlib is using. Has anyone come up with a workaround (or fix) for either Xlib or xperfmon? eric ...!pyramid!eric -- eric ...!pyramid!eric
janssen@holmes (Bill Janssen) (06/26/89)
You might try looking for bytes on the wire, thusly: while (1) { if (XQLength(disp) > 0) { read events and act on them } choose a timeout for the select - see below call select() on the pty and XConnectionNumber(disp) if (the select timed out) { if (the window needs updating) update it if (there might be stuff to flush to the X server) { XSync(disp,False); /* see below */ } continue; } if (select indicates something on the X connection) { + unsigned long count; + + if (ioctl(ConnectionNumber(disp), FIONREAD, &count) == 0 + && count < 1) + EOFonXconnectionRoutine(); + else XEventsQueued(disp,QueuedAfterReading); continue; } if (select indicates something on the pty) { handle stuff on the pty } } Should work on SunOS 3.5. Properly speaking, the routine to be called should handle exceptions on that fd, not just EOF. Include sys/filio.h to get the definition of FIONREAD. Bill Bill Janssen janssen@xerox.com (415) 494-4763 Xerox Palo Alto Research Center 333 Coyote Hill Road, Palo Alto, California 94304