From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2006-05-23 19:13:46
Thanks for your reply. One thing I forgot to mention is that
this is also in the context of writing a proposal for TR2 based
on Boost.Asio. Since the filesystem library has already been
accepted for TR2 I want to keep the low-level error approach as
consistent as possible with it.
> The other problem was that Windows and Unix have a different
> models of handling errors. On Unix, errors are "syscall
> sensitive", i.e. there is a limited number of error codes and
> they sometimes mean slightly different things depending on
> which system call was invoked. On the other hand, on Windows
> the error space is "flat" and any system call can essentially
> return any of the (10000 or so) error values.
Yep, this is exactly the main problem I'm facing. Even on
windows the error space may not be truly flat once you
incorporate other "system" libraries like OpenSSL say, which use
their own error space.
> d) The error handler would then get invoked with the
> SysResult and it could decide based either on the "System
> independent" or "system specific" error code, what it should
> do. The error handler would return one of "CONTINUE",
> "RETRY", "FAIL" enumerations. The first and second are, I
> think, self-explanatory. The third would cause the
> surrounding code to trow an exception, similar to
> system_error. My default error handlers would do something
> sensible like retry on EINTR and and throw on other error
> conditions. I also had a non-throwing version.
This approach is similar to what's currently in asio:
- The synchronous functions have overloads that take an
Error_Handler function object that can be used to customise
what happens when an error occurs. However the Error_Handler
does not allow the operation to be restarted.
- The higher level asio::read() and asio::write() functions also
have a Completion_Condition function object which is passed
the error code and the amount of bytes transferred. The return
value from this function object indicates whether the
underlying operation should be restarted.
> i) Assuming that your "high-level" system operation is
> implemented in terms of several system calls, what is a good
> way handling system-specific error codes? My error handlers
> had the possibility of handling not only the "high- level"
> library errors but also use the low-level system errnos.
> However, as you can see, this breaks encapsulation by making
> assumptions about how the function is implemented in terms of
> the underlying syscalls.
For most functions in the current asio implementation I think
this isn't too bad. They are often relatively thin wrappers
around the existing system calls, and in many cases there is
already mapping to just one system call. In other cases I think
it will have to be a best-effort translation of the error code
to something sensible.
> ii) The same issue I described above applies equaly well to
> other functions implemented in terms of several "high-level"
> (library) system calls. To be able to use the SysResult
> effectively, you would need to know which function generated
> it, again breaking encapsulation.
I think the idea with the error_code/system_error approach is to
leave the error_code object with very little other than the
system error number. However in the case of an exception, the
system_error's "what" string can contain more information about
the context where the error was generated.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk