[racket-dev] Safe errno access across platforms.

From: Nathan (nejucomo at gmail.com)
Date: Mon Dec 3 17:37:36 EST 2012

Hello,

I'm new to racket, and only mildly familiar with scheme, so I
apologize if I'm missing important details.

Whenever an error occurs related to a C interface which uses "errno"
to signal the kind of error, I propose the associated racket exception
should capture this errno value separately from the error message.  I
propose exposing the literal value and also a cross-platform way to
determine the symbolic name for that value on the current platform.

The reason is that it is often desirable to distinguish error causes
with as fine a resolution as the platform provides.  The specific
example that lead me to this issue is that I want to read a file, but,
in the case that the file is not present, return a default value.  In
any other case (such as incorrect permissions, or should the path
refer to a directory instead of a file), I want the error to
propagate.  A work-around for my particular case is to check for the
file's existence before opening it for reading, but notice that this
introduces one more race-condition, so I prefer my original strategy.
This is just a single case, and I expect in general it will be useful
or necessary to distinguish errno values.

I chatted with dyoo on the freenode irc channel and he suggested I
send mail to this list, because this would be a backwards incompatible
change.

I'm not too familiar with racket, so there may be much better API
designs, but my first idea was to add a new base exception struct
along the lines of (struct exn:fail:errno exn:fail (errno)) and some
separate module for translation with errno->symbol and symbol->errno.
Maybe it's nicer to just include the symbol directly in the exception
structure.

There are a few implementation details I'd caution about:

In general, "errno" may be a macro, so a simple ffi wrapper may not be
cross-platform (according to the manpage).  The value of errno is in
thread-local storage, and I have no idea how that relates to racket
thread safety.

Including *only* the symbolic name of an errno would be a mistake,
IMO, because I'm an anti-fan of abstractions hiding the truth.  OTOH,
I'm also a fan of abstractions and interfaces, so excluding the
symbolic name is essential for writing clean cross-platform code.


Regards,
Nathan Wilcox

ps: So far I'm really enjoying racket!  The documentation is
excellent; there's a debian package I can simply apt-get; and I've
been playing with the custom language design features which are much
nicer than I realized for scheme-likes.  I had always thought the
status quo was splicing with quasiquote so the syntax features are a
wonderful surprise.  Also, I'm very interested to explore the
sandboxing features, but I haven't yet learned them in detail.  I'm
quite pleased they include time and memory constraints.

Posted on the dev mailing list.