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

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

Le mercredi, 4 fÃvrier 2015 Ã 15:09, Thomas Leonard a Ãcrit :
> I don't think exception vs error code is a reliable way to divide
> these cases up. Having your FS return `Block_error indicates a serious
> problem that might require terminating the unikernel, whereas getting
> a Division_by_zero exception from your HTTP handler is likely fairly
> harmless. Whether an exception/error is serious depends more on the
> importance of the thing that raised it.

You may want to handle unexpected exceptions before the toplevel of your 
program but you want to keep the two error reporting mecanisms separate 
(unexpected programming errors vs expected errors). Both are able to flow up 
and be handled up to wherever you wish.

> In this case, we can imagine a fail-safe FS functor that wraps all the
> calls in the FS API so that if any one of them throws an unexpected
> exception then it unplugs the underlying block device. No need to kill
> everything.

You could turn these internal *unexpected* programming errors into an 
[`Internal_error of exn] *expected* error which allows client to e.g. unplug 
the device in this case. Here again I'd suggest a trap abstraction that has a 
catch all handler for the exceptions:  

type 'a trap
val trap : ('a -> 'b) -> 'a -> 'b trap
val untrap : 'a trap -> ('a, [> `Internal_error of exn]) result
â (* maybe a few other combinators that handle nicely 'a trap when 'a = ('b, 
'c) result and a few other to act directly on top of the concurency monad *)

By judiciously placing trap values in mirage signatures you could enforce safe 
points in the system and their handling (or not if the users lets the expected 
error flow up) by the component users.  

I didn't think much about this but I suspect the trap could be directly bundled 
in mirage's definition of the `result` type.  

> However, different functions return different sets of errors. For
> example, BLOCK.read shouldn't return `Is_read_only. Can we handle
> that?

type write_error = [ `Read_only | â ]
type read_error = [ `Write_only | â ]
type error = [ read_error | write_error ]

val BLOCK.read : â -> (int, [> read_error]) result
> I've added some error_message (error -> string) functions, but this
> might be better. I haven't used formatters much, so don't have an
> opinion here.

Actually this should have read `pp_error : formatter -> error -> unit`. 
Formatters are nicer if you want to pretty print errors. Once you have a base 
set of combinators for printing options, lists, etc. (which are sadly missing 
from the stdlib) they compose well. To string functions are just a 
`Format.asprintf "%a" pp_error`, away.  

> But I think we still need an additional "exn_of_error" here because
> whether something is a "dynamic" (expected) error or a bug changes as
> the error is propagated.
> For example, an XML parser probably regards a malformed document as a
> dynamic error (`Malformed of malformed), which its caller may want to
> handle. But if the caller is trying to load its configuration file
> from a crunch FS, then malformed XML is a programming bug and should
> be thrown as an exception.

Wouldn't you simply turn that into an assert false (or let's say 
invalid_argument if you want to pp the message) ?  



MirageOS-devel mailing list



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