file: module and character special files

Patrik Nyblom pan@REDACTED
Fri Jan 30 17:15:39 CET 2004


They say I should comment on this, so I'll do it.

The interesting part is last, so read from the end if you're only 
interested in that :-)

Richard A. O'Keefe wrote:

>I asked why file: doesn't handle /dev/null correctly.
>"Erik Stenman" <Erik.Stenman@REDACTED> and matthias@REDACTED
>both pointed me to Patrik Nyblom's explanation from nearly four
>years ago:
>The argument goes like this:
>(a) it is hard to get non-blocking I/O going portably across UNIXes.
>(b) therefore the file: module relies on a driver which does blocking
>    I/O, which only really works if the I/O *doesn't* block, means
>    that only "fast" devices are supported.
>(c) which means that only 'regular' files are supported.
>(d) which is why /dev/null is rejected.
>(e) which is why you get the "eisdir" error message.
>Ad (e): there is no excuse for giving the wrong error message.
>The error message should indicate plainly that only regular files
>are supported; it certainly should NOT state something that is
>patently untrue!  If nothing else is done, 4 years is quite long
>enough for a badly misleading message to be KNOWN to lurk in the
>system; time to fix it.
As I originally said, the return value is misleading. The return value 
is one issue, the fact that
device files cannot be opened is another. My post was aimed at 
explaining the reason, not the exact
return value. As you focus the argumentation on the return value in 
itself, I'll try to explain that as well...

Someone decided, a long time ago, that EISDIR was a good return value 
here, when something
on the line of "this is not a regular file" would have been better. That 
may have been a bad choise.
However, changing return values isn't all that popular among people 
having miljons of lines of code
slushing around in systems supposed to have an ISP of 99.999 or better. 
Therefore the prio of such a
change isn't all that high. It's not really a big deal either, honestly. 
I think most users think there are
larger issues we should work on, but I might be wrong :-)

>Ad (d): /dev/null is the fastest device there is.  Read from it,
>and you're immediately told "end of file" without any peripheral
>activity at all.  Write to it, and the bytes are immediately thrown
>away without any peripheral activity at all.  Nyblom's argument
>about tape drives blocking Erlang processes for long times is
>NO ARGUMENT AT ALL against supporting /dev/null.  /dev/null is
>so useful for testing that if the driver has to make a special case:
>    if stat(2) says the file is a regular file
>    or stat(2) says the file is a character special file
>       and the name is /dev/null
>    then open the file
>    otherwise report "regular file needed"
>then so be it.  I _think_ the requisite change is to
>    erts/emulator/drivers/unix/unix_efile.c
>in the function efile_openfile(), where the lines
>    if (!ISREG(statbuf)) {
>        close(fd);
>        errno = EISDIR;
>        return check_error(-1, errInfo);
>    }
>should be
>    if (!ISREG(statbuf)
>     && !(ISDEV(statbuf) && 0 == strcmp(name, "/dev/null"))
>    ) {
>        close(fd);
>        errno = EISDIR;
>        return check_error(-1, errInfo);
>    }
>This is also the place where something should be done about (e),
>even if it does mean defining an ENOTREG error number that is not
>one of the usual UNIX error numbers.
I get your point, but obviously the suggested patch would not solve any 
real problem.

With your patch applied:
Erlang (BEAM) emulator version 5.4 [source] [threads:0]

Eshell V5.4  (abort with ^G)
1> file:open("/dev/null",[read]).
2> cd("/dev").                  
3> file:open("null",[read]).
This is of course easy to fix, but it indicates that the 
string-matching-magic-filename approach is no good.
In fact the approach works even worse for other obvious cases, i.e. with 
a hard link to /dev/null, opening /dev/zero (which is bleeding fast as 
well) etc.

Whoever wrote the original file driver draw the line at regular files, 
as that can be determined.

Whoever that person was, I think he or she was right in doing this.

However, with a different implementation than the original, the line 
could be drawn somewhere else, see below.

>Ad (c): it has NOT been true for a long time that "operations won't
>block" on regular files.  Not since RFS and NFS came into use.
>The file system I see on my main machine is spread across three
>different nodes; the machine I'm posting from brings in another.
>I have known read() operations on what *looked* like "regular" files
>take 30 seconds.  (On one memorable occasion, several hours.)
It is true that NFS can make reading from regular files block. We cannot 
handle that
and we cannot "see" if a file is on local or remote filesystem from the 
driver. The OS'es
don't provide sufficient interfaces to del with such things.

We do not recommend people writing real-time systems relying on NFS over 
unstable network
connections either, but that's beside the point.

Still, it would not help to use select or poll. File handles for NFS 
files behave like file handles for
any other file system, they are always available for reading and 
writing. It's not unsolvable, but
looking for the unix-dialect where select/poll can be used to se if the 
nfs server is accessible is
not a feasible solution.

>Ad (b): I don't really understand the present design (the internal
>documentation of the file driver code is, shall we say, sparse), so
>I can't comment.
>Ad (a): while there may be UNIX systems whose implementors have
>disgraced themselves by failing to make poll() or select() work
>on files, in the light of the fact that "regular" file operations
>can't really be trusted to be fast, it might be a good thing to have
>a poll/select-based driver that could be used in UNIX systems where
>those functions *do* work with files.  (This is the kind of thing that
>./configure can figure out.)
I wrote "lots of u*x'es" in the four year old letter, I should have 
written "any unix system we know of" instead.
If things have changed during the last years, that might have been 
interesting if we hadn't found a more
general solution to the problem.

Note that select/poll does indeed "work" on regular files in the sense 
that they don't
result in an error return, they simply always signal that data is 
writable to and
readable from the file descriptor regardless of the actual facts.

End of implementation discussion. Now comes the interesting part:

Tony Rogvall (together with others) has made a remarkable
*real, working, and portable* implementation
of a threaded file driver, submitted it to us, and that is the one 
nowdays present in the emulator.

That driver, to some extent, solves the NFS problem. It's working well for
all unixes that haven't failed to implement threads properly in the kernel
(maybe those without kernel threads are the one that really have 
disgraced themselves :-).

Among platforms where this work well are Solaris, Linux, Windows and 
many others.

This obviously means that given a large enough thread pool, opening 
device files like /dev/null with this driver
would be a much better idea than it was in the single threaded case. So, 
what *should* be changed in the file driver,
is more on the lines of

If the file is regular then
  If the file is not a directory and
   you have more than one I/O thread and
    you have chosen to explicitly enable the feature by some means then
    open the thing anyway
    return some error

Were "return some error" actually still might mean "eisdir", especially 
if one wants
the fix done in time for the next release...

>Erik Stenman ended his reply thus:
>	That post ends with:
>	  "Maybe an alternative "any-type-of-file-driver" which uses
>	   threads/separate processes would be nice though."
>	Maybe we can get OTP to implement this if there are enough requests
>	for a feature like that on the list, or maybe someone already has 
>	such a driver somewhere that could be contributed to the community?
So, allowing device files to be opened from within the file driver could
be done.  

Is there really anyone needing this? Speak up in that case and someone 
will add it. The return value is another issue
though, that needs confirmation from the ones actually paying for all 

>I was trying to "sell" the idea of using Erlang to a consultant.
>What he _really_ wanted was a framework where he could open
>URIs with at least the file, http, and ftp schemes either for input
>or for output, like you can in Java.  Now, by using an outboard
>program like cURL, this could be reduced to the problem of UNIX pipe
>I/O, but that does mean that a driver that can handle both files
>(with all the network delays that are implied by networked/remote/
>shared file systems) and pipes (with all the delays implied by running
>programs that may have to wait for other things to happen) would be of
>use to Erlang.  It's a *much* bigger problem than just /dev/null, and
>a much bigger opportunity.
Nice idea, with the change suggested above and a bunch of I/O-threads, 
nothing in Erlang stops you from writing such a thing.
Ftp is already there, http is a piece of cake, file I/O with threads is 
non-blocking... A simple wrapper and some HTTP stuff.

Best regards,

More information about the erlang-questions mailing list