[erlang-questions] Issues with stdin on ports

Per Hedeland per@REDACTED
Tue Jul 30 15:04:02 CEST 2013


"Richard A. O'Keefe" <ok@REDACTED> wrote:
>
>On 30/07/2013, at 2:13 AM, Per Hedeland wrote:
>> 
>> FWIW, I definitely agree that this is a missing piece of functionality.
>
>Oh it's present in several languages.  You could argue that it's missing.
>But is it missing like a car radio in a car that lacks one,
>or is it missing like an ejector seat in a car that lacks one?

I think it's more like a parking brake - not strictly needed, but quite
useful, and definitely not dangerous in any way.

>>> popen(<command>, "r") reads the output of
>>> the command and popen(<command>, "w") writes to the input of the command.
>> 
>> popen() is effectively a convenience function to abstract away the
>> somewhat non-trivial application of pipe(), fork(), close(), and
>> execve() that is required to set things up correctly for two particular
>> and common usages of pipes in application code. (It is not used by
>> common shells to implement pipelines though.)
>
>Having implemented popen() for two other high level languages, I know that.
>The fact that common shells do not use it is irrelevant.

No, it is quite relevant, since it's one example of how popen() doesn't
define the "pipe API" in C, anymore than stdio defines the "I/O API" (in
fact considerably less, since popen() is far more limited relative to
the underlying basic API, and unlike stdio lacks the portability promise
of being ANSI standard).

>>> There isn't even any standard _term_ for talking about connecting to both
>>> stdin and stdout of a command in UNIX, and that's because it's an
>>> incredibly easy way to deadlock.
>> 
>> There is no need to have a term for it, since all you need is two pipes,
>> one for each direction
>
>Non-sequitur.  If it's a thing you need to do often, it's a thing you
>need to be able to talk about.

Ditto - I didn't claim that it's something you need to do often, only
responded to your claim that the absence of a term is due to the dangers
of using it.

>>  (the risk is of course reduced due to the fact that the
>> VM does non-blocking I/O).
>
>And *that* is the thing that saves Erlang.

Yes, I was actually overly cautious with "reduced" - it completely
eliminates the risk of deadlock (at lest as long as there is no way to
block input from a port).

>You may have misunderstood me.
>>>>> THE POPEN INTERFACE <<<< prevents C users doing this.

Well, that's not what you said, so I guess the problem wasn't a case of
misunderstanding.

>For that matter, it's not beyond the abilities of, say, the glibc
>authors, to extend their implementation of popen to support "r+"
>or "w+" modes, if there were much demand for it.  (Oddly enough,
>Mac OS X 10.7.5 _does_ support "r+" mode, but the Linux I checked
>does not.  Weird.)  I have _never_ been able to understand the
>differences between Mac OS X and POSIX.

This is probably due to its relationship with FreeBSD, and the
explanation seems to be present in the popen(3) man page of both:

  Because popen() is now implemented using a
  bidirectional pipe, the mode argument may request a bidirectional data
  flow.

I.e. *pipes* are bidirectional on FreeBSD (and other *BSD AFAIK) - I'm
not sure whether they actually are on MacOS X, the pipe(2) man page
certainly doesn't say so (which it does on FreeBSD). It may well also be
the case that MacOS X just copied the BSD popen(3) man page without
bothering to make sure that it worked as advertised with their
underlying pipe(2). (Side note, FreeBSD pipe(2) mentions that SysVR4 was
actually first with bidirectional pipes, and indeed Solaris has them too
- but according to its popen(3C), doesn't support "r+".)

Anyway, interesting as it may be, I'm afraid that this will have to
conclude my participation in a discussion about pipes in C and the
potential dangers of using them in other ways than popen() allows for -
it is after all completely off-topic in this thread at least.

To summarize: Erlang open_port/2 *by default* creates a bi-directional,
deadlock-free communication channel to the external process. The
question at hand is just whether adding a way to close only the "output"
side of this channel has merit.

--Per



More information about the erlang-questions mailing list