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

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



On 22 March 2015 at 15:02, Daniel BÃnzli <daniel.buenzli@xxxxxxxxxxxx> wrote:
> Le dimanche, 22 mars 2015 Ã 14:43, Thomas Leonard a Ãcrit :
>> Yes, but the question is whether this information is worth the
>> overhead.
>
> Again programmatically there's no overhead if you are using the right set of 
> combinators and type definitions. You can say there is a performance overhead 
> but at a certain point you have to choose whether you want correct, safe and 
> reliable systems or favour performance. I'm strongly in favour of the former 
> and have both whenever possible.
>
>> - We must assume that some implementation of a Mirage module type may
>> produce an error (they're all about I/O, after all), so annotating
>> every function to say this doesn't provide any extra information.
>
> This misses the point. Having every functions annotated provides you 
> information *in the type system* which gives you a mechanism to *enforce* 
> good and correct error handling in the program.
>
> Using exceptions doesn't allow you to enforce error handling and is otherwise 
> very dangerous because 1) You basically don't know when they happen except 
> through documentation, so they are easy to miss and not handle them (if 
> documentation exists at all...) 2) They disrupt your whole callstack, 
> possibly leaking resources and putting your program in a bad state by 
> breaking invariants that should hold in our system  3) The source of the 
> exception may be hard to track 4) They are hard to reason about and handle 
> correctly.

The only case of handling the current polymorphic errors in Mirage so
far presented is this case from ocaml-tls (thanks David!):

https://github.com/mirleft/ocaml-tls/blob/master/mirage/tls_mirage.ml#L51

  let lift_result = function
    | `Error e          -> `Error (`Flow e)
    | `Eof | `Ok _ as r -> r

  let check_write flow f_res =
    let res = lift_result f_res in
    ( match (flow.state, res) with
      | (`Active _, (`Eof | `Error _ as e)) ->
          flow.state <- e ; FLOW.close flow.flow
      | _ -> return_unit ) >>
    return res

As you say, it's easy to reason about this code if we assume that
exceptions don't exist:

- If the underlying FLOW returns any error on write, then the TLS
state transitions to `Error and cannot be used again and the FLOW is
closed.

However, exceptions do exist in OCaml. The actual behaviour therefore
is something like:

- On `Refused, `Timeout or `Unknown, the flow is closed and the TLS
system transitions to `Error.

- On Division_by_zero, Not_found, Assert_failure or Stack_overflow,
the flow remains open and the TLS state can continue to be used.

It seems unlikely to me that this is the desired behaviour. If all
errors were exceptions then the code would likely handle all these
cases.

(however, it's not clear to me exactly what this code is trying to
achieve, so I could be wrong)


-- 
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
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel

 


Rackspace

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