[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MirageOS-devel] Error handling in Mirage - request for comments!

On 4 February 2015 at 13:01, Leo White <lpw25@xxxxxxxxx> wrote:
> Hi all,
> As this discussion keeps on running, I thought I would add a couple of
> thoughts:
> - The problem with using exceptions for returning errors is that it
>   becomes very difficult to distinguish between a dynamic error that is
>   part of normal use (e.g. this network connection failed) from a
>   programming error (e.g. Not_found accidently leaked from a use of
>   List.find, an assert false triggering). This makes it hard to produce
>   the correct behaviour in all cases: there are applications for which
>   it would be better to kill everyting on detecting a programmer error
>   rather than risk continuing in an unstable state.
> - The problem with using Lwt.t as your error monad is that it becomes
>   difficult to distiunguish between synchronous things that may return
>   errors, asynchronous things that may return errors, and asynchornous
>   things that should not return errors. It also seems tied up with the
>   exception mechanism, which leads to the same problem as my previous
>   point.
> Personally, I would probably suggest that all Mirage modules/module
> types include in their signatures:
>   type error
>   val pp_error : formatter -> error -> string
> For cases where an error can reasonably be matched on and handled
> specially, this should be exposed in the signature:
>   type error = private [> `Foo of foo | `Bar of bar]
>   val pp_error : formatter -> error -> string

I've had a go at writing this proposal up ("system 5"):


I think someone who wants to advocate this style should check it /
change it. It probably needs some worked examples showing it being
used too.

> Some nice combinators should be provided for using ('a, 'b) Result.t and
> ('a, 'b) Result.t Lwt. and for lifting an ('a, Foo.error) Result.t into
> an ('a, Bar.error) Result.t.
> Exceptions that escape their intended scope, should always be treated as
> a programming error.

Yes, by definition. But what should the "intended scope" be, and how
do we ensure the producer and consumers of the exception agree?

In 0install, for example, there is a single "Safe_exception"
constructor used for any non-bug human-readable error that should
abort without showing a stack trace ("File '...' not found", etc). If
they make it to the top-level, they get printed to stderr. In the GUI,
they appear in an error dialog box. Any other kind of exception
reaching the top-level is considered a bug. For a library, these kinds
of thing need to be documented.

> The various "finally" functions for resources
> should catch and reraise them, so that they can reach the outermost
> scope which knows how best to deal with a programming error in the
> particular application. The same goes for binding on an Lwt thread which
> raised an exception or failed: it should cause an exception to be raised
> to reach the outermost level.
> The aim here is still to take the erlang-style kill the component that
> failed and try again approach, but to ensure that there are two distinct
> return paths for regular errors and programming errors. The secondary
> aim is to have module signatures which give a clear indication of
> intended use.

Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

MirageOS-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.