[PATCH] Handling of stdin as non-tty and stdout as tty (R6B-0)
Sun Nov 28 14:59:36 CET 1999
Samuel Tardieu <sam@REDACTED> wrote:
>The following patch fixes a huge CPU hog when the standard input of the
>Erlang process is not a tty while the standard output is.
>ERRNO_BLOCK is used to unblock the "cat" process; the code in the release
>would however continue to try to "cat" the data.
Thanks a lot for tracking this down - there have been some reports about
this "looping process", but the exact circumstances haven't been pinned
down before - and it doesn't happen on Solaris or other Unices that have
the "true" O_NDELAY semantics (a read() that would block returns 0 -
pretty useless in the "normal" case).
The real problem is of course the very existence of this "cat" process
though - it can't be described as anything other than a kludge, and as
you can see from the comments in the code it has had a history of
problems, and I'm sure we haven't seen the last one. If someone could
come up with a better way to solve the underlying problem, I think it
would be very appreciated.
The underlying problem, in case it isn't obvious, is that the Erlang
runtime system wants to do all its I/O in non-blocking mode - otherwise
the whole system could hang if e.g. a port program misbehaved - and that
this doesn't work well when you interactively do something like:
% some_program | erl
In this case, it used to be that 'erl' set its stdout (i.e. the user's
tty) in non-blocking mode - and this would apply also to 'some_program''s
stdin (the same tty), which 'some_program' typically wasn't happy with
(i.e. it would just see an error on read() and give up).
The "solution" was to internally interpose the "cat" process, making the
actual picture become:
% some_program | erl | "cat"
- in which case 'erl' can happily set its stdout (which is now a pipe)
in non-blocking mode without affecting 'some_program' (and "cat"'s
stdout would be in blocking mode, but that's OK).
The primary alternative to using the "cat" process is to simply not set
stdout in non-blocking mode in the "problematic" case(s) - this has the
obvious disadvantage that the system could hang if it needed to send
something to stdout and this wasn't possible for some reason (e.g. the
user had hit ^S); also reliably detecting the "problematic" case(s)
isn't entirely trivial.
More information about the erlang-questions