let section_ctxt ctxt f =
  let old_tear_down =
    OUnitShared.Mutex.with_lock
      ctxt.shared ctxt.tear_down_mutex
      (fun () -> ctxt.tear_down)
  in
  let clean_exit () =
    OUnitShared.Mutex.with_lock
      ctxt.shared ctxt.tear_down_mutex
      (fun () ->
         List.iter (fun tear_down -> tear_down ctxt) ctxt.tear_down;
         ctxt.tear_down <- old_tear_down)
  in
    OUnitShared.Mutex.with_lock
      ctxt.shared ctxt.tear_down_mutex
      (fun () -> ctxt.tear_down <- []);
    try
      let res = f ctxt in
        clean_exit ();
        res
    with e ->
      clean_exit ();
      raise e