[Openmcl-devel] Some smoking gun terminal weirdness

Ron Garret ron at flownet.com
Fri Mar 16 14:24:18 PDT 2018

On Mar 16, 2018, at 10:33 AM, Ron Garret <ron at flownet.com> wrote:

> On Mar 16, 2018, at 10:15 AM, Ron Garret <ron at flownet.com> wrote:
>> On Mar 16, 2018, at 5:18 AM, Jan Gajdoš <y at gajdos.se> wrote:
>>> Probably not CCL's problem.
>> Except that I cannot reproduce this behavior in C.  I’ve tried a zillion variations and they all work perfectly.
> Definitely a CCL problem.  I have now reproduced it on Linux and using iTerm.

OK, I think I have finally figured this thing out.

There are two different things going on here.  One is a CCL bug, the other isn’t.  The bug is Mac-only.

The first thing that is going on is that normal CCL I/O is buffered, and so there can be (and usually is) a delay between when you call a normal CCL output function like PRINT or FORMAT and when the underlying OS call is made to actually produce the output.  This can interleave badly with calls to turn raw input mode on and off.  Turning raw input mode on does not just affect how input is handled, it also changes how output is handled.  In particular, #/Newline characters in normal mode a translated into CRLF, but in raw mode are output as linefeeds only.  This is the reason for the weird timing-dependent indentation on some of the examples I posted: raw mode was actually being turned off in the middle of flushing the output buffers.

The second thing that is going on is that on a Mac, when you turn on raw mode, all output is blocked until there is a keystroke in the input queue.  Here’s a demo:

(defun demo ()
  (flet((out (s) (with-cstrs ((cs s)) (#_write 1 cs (length s)))))
    (out "Press any key...")
      (out "You won't see this")
      (out "You will see this"))))
? (demo)
Press any key...You will see this

This is reliably reproducible in both Terminal and iTerm.  The corresponding C code does not exhibit this behavior.  Note that you don’t actually have to read the character to break the logjam.  Replacing READ-CHAR with SLEEP will work if you press a key during the sleep.

Here’s the C code just in case you want to try it:

#include <unistd.h>
#include <termios.h>
#include <strings.h>

int main(void) {

  char*	s = "You will see this";

  struct termios attrs, attrs1;

  tcgetattr(0, &attrs1);
  tcsetattr(0, TCSAFLUSH, &attrs);

  write(1, s, strlen(s));

  tcsetattr(0, TCSAFLUSH, &attrs1);

More information about the Openmcl-devel mailing list