[racket-dev] Safe errno access across platforms.
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.