[m-rev.] IO error type

Volker Wysk post at volker-wysk.de
Thu Aug 18 01:35:34 AEST 2022

Am Mittwoch, dem 17.08.2022 um 19:31 +1000 schrieb Julien Fischer:
> On Wed, 17 Aug 2022, Peter Wang wrote:
> >    :- type system_error.
> > 
> >    :- func make_io_error(system_error, string) = io.error.
> > 
> >    :- pred get_system_error(io.error::in, system_error::out)
> >        is semidet.
> > 
> > That is, to introduce a backend/platform specific system_error
> > type,
> > and add a field for system_errors in the io.error type.
> > (It would still be possible to construct an io.error without a
> > system_error value.)
> That was my preferred approach as well, however on Windows there is
> samll wrinkle with this: some of the system error codes we return are
> *not* errno values but instead are system error codes (e.g. of the
> kind
> returned by GetLastError()). So at least on Windows, if you embed a
> raw
> system error in an io.error, you have the additional problem of
> having
> to know what kind of error code it is.

Going with the system_error approach, you should make system_error a
discriminated union of errno values and system error codes. But I think
the errno (name or value) should be made accessible even under Windows.
So the error handling can be made more platform independent.

So my idea would be to introcude *two* new fields in the io.error type:
an optional field for the errno and an optional new system_error field.
The system_error would be platform specific, whereas the errno field
would be POSIX specific. Something like this:

:- type errno == int.

:- type error ---> error(
   ...,                 % possibly some more error information
   maybe(errno),        % errno value
   maybe(system_error)  % platform specific parts
An additional, also optional field for a filename should also be added,
since this already is the de facto standard for POSIX error handling -
for the POSIX calls which operate on a file or directory. 

> (This is not a problem with the existing code, since all error codes
> are turned into error messages fairly close to the point where they
> occur, and at those points we know what kind of error code it is.)
> Looking a bit closer: the calls to GetLastError() occur pretty much
> in the dir module, so maybe we can re-arrange how it handles errors
> to avoid that?
> > If we add your suggestion to allow converting an io.error to a
> > name,
> > we might have:
> > 
> > 	% Returns a standard error name if the given error corresponds
> > 	% to a system error known to the Mercury system, e.g. "ENOENT"
> > 	% (or possibly the name of a Java or C# exception?).
> Given that C# and Java exceptions are usually arranged in a class
> hierarchy, which name would you return?

I don't know, but those exceptions should also be equiped with an errno
value, if possible. If this can be queried somehow (such as with the
errno variable immediately after the call?).

> > 	% Fails if the error is not a system error, or if the error is
> > 	% not one recognised by the Mercury system.
> > 	%
> >    :- pred get_error_name(io.error::in, string::out)
> > 	is semidet.
> > 
> > 	% As above, but takes a system_error instead.
> > 	%
> >    :- pred get_system_error_name(system_error::in, string::out)
> > 	is semidet.
> My preference would be for the standard library to simply give access
> the the system error value and leave it for other system-specific
> libraries (e.g. the POSIX binding) to provide further facilities for
> examining it.
> Julien.

More information about the reviews mailing list