diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 55c2a061f4..6bf99cda95 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -273,6 +273,13 @@ let may f = function type ('a, 'b) maybe = Either of 'a | Or of 'b +let protect ~f ~finally = + let r = + try Either (f ()) + with exn -> Or exn in + finally (); + match r with Either ret -> ret | Or exn -> raise exn + let istty chan = Unix.isatty (Unix.descr_of_out_channel chan) diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli index 214f04d1b9..7172da9825 100644 --- a/mllib/common_utils.mli +++ b/mllib/common_utils.mli @@ -130,6 +130,18 @@ val may : ('a -> unit) -> 'a option -> unit type ('a, 'b) maybe = Either of 'a | Or of 'b (** Like the Haskell [Either] type. *) +val protect : f:(unit -> 'a) -> finally:(unit -> unit) -> 'a +(** Execute [~f] and afterwards execute [~finally]. + + If [~f] throws an exception then [~finally] is run and the + original exception from [~f] is re-raised. + + If [~finally] throws an exception, then the original exception + is lost. (NB: Janestreet core {!Exn.protectx}, on which this + function is modelled, doesn't throw away the exception in this + case, but requires a lot more work by the caller. Perhaps we + will change this in future.) *) + val prog : string (** The program name (derived from {!Sys.executable_name}). *) diff --git a/v2v/windows.ml b/v2v/windows.ml index 75d7010368..f92447d427 100644 --- a/v2v/windows.ml +++ b/v2v/windows.ml @@ -55,16 +55,16 @@ and (=~) str rex = let with_hive (g : Guestfs.guestfs) hive_filename ~write f = let verbose = verbose () in g#hivex_open ~write ~verbose (* ~debug:verbose *) hive_filename; - let r = - try + protect ~f:( + fun () -> let root = g#hivex_root () in let ret = f root in if write then g#hivex_commit None; - Either ret - with exn -> - Or exn in - g#hivex_close (); - match r with Either ret -> ret | Or exn -> raise exn + ret + ) ~finally:( + fun () -> + g#hivex_close () + ) (* Find the given node in the current hive, relative to the starting * point. Returns [None] if the node is not found.