Skip to content

Commit d20a902

Browse files
authored
Merge pull request #295 from ocaml-multicore/try-to-cleanup
Run cleanup in the presence of exceptions
2 parents 67fc59f + 9b61770 commit d20a902

File tree

8 files changed

+119
-10
lines changed

8 files changed

+119
-10
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changes
22

3+
## Next version
4+
5+
- ensure `cleanup` is run in the presence of exceptions in
6+
- `STM_sequential.agree_prop` and `STM_domain.agree_prop_par`
7+
- `Lin_thread.lin_prop` and `Lin_effect.lin_prop`
8+
39
## 0.1.1
410

511
- #263: Cleanup resources after each domain-based `Lin` test

lib/STM_domain.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ module Make (Spec: Spec) = struct
2626
let dom2 = Domain.spawn (fun () -> Atomic.set wait false; try Ok (interp_sut_res sut cmds2) with exn -> Error exn) in
2727
let obs1 = Domain.join dom1 in
2828
let obs2 = Domain.join dom2 in
29+
let () = Spec.cleanup sut in
2930
let obs1 = match obs1 with Ok v -> v | Error exn -> raise exn in
3031
let obs2 = match obs2 with Ok v -> v | Error exn -> raise exn in
31-
let () = Spec.cleanup sut in
3232
check_obs pref_obs obs1 obs2 Spec.init_state
3333
|| Test.fail_reportf " Results incompatible with linearized model\n\n%s"
3434
@@ print_triple_vertical ~fig_indent:5 ~res_width:35

lib/STM_sequential.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ module Make (Spec: Spec) = struct
1818
let agree_prop cs =
1919
assume (cmds_ok Spec.init_state cs);
2020
let sut = Spec.init_sut () in (* reset system's state *)
21-
let res = check_disagree Spec.init_state sut cs in
21+
let res = try Ok (check_disagree Spec.init_state sut cs) with exn -> Error exn in
2222
let () = Spec.cleanup sut in
23+
let res = match res with Ok res -> res | Error exn -> raise exn in
2324
match res with
2425
| None -> true
2526
| Some trace ->

lib/lin_effect.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,14 @@ module Make_internal (Spec : Internal.CmdSpec [@alert "-internal"]) = struct
9696
let sut = Spec.init () in
9797
(* exclude [Yield]s from sequential prefix *)
9898
let pref_obs = EffTest.interp_plain sut (List.filter (fun c -> c <> EffSpec.SchedYield) seq_pref) in
99-
let obs1,obs2 = ref [], ref [] in
99+
let obs1,obs2 = ref (Ok []), ref (Ok []) in
100100
let main () =
101-
fork (fun () -> let tmp1 = interp sut cmds1 in obs1 := tmp1);
102-
fork (fun () -> let tmp2 = interp sut cmds2 in obs2 := tmp2); in
101+
fork (fun () -> let tmp1 = try Ok (interp sut cmds1) with exn -> Error exn in obs1 := tmp1);
102+
fork (fun () -> let tmp2 = try Ok (interp sut cmds2) with exn -> Error exn in obs2 := tmp2); in
103103
let () = start_sched main in
104104
let () = Spec.cleanup sut in
105+
let obs1 = match !obs1 with Ok v -> ref v | Error exn -> raise exn in
106+
let obs2 = match !obs2 with Ok v -> ref v | Error exn -> raise exn in
105107
let seq_sut = Spec.init () in
106108
(* exclude [Yield]s from sequential executions when searching for an interleaving *)
107109
EffTest.check_seq_cons (filter_res pref_obs) (filter_res !obs1) (filter_res !obs2) seq_sut []

lib/lin_thread.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ module Make_internal (Spec : Internal.CmdSpec [@alert "-internal"]) = struct
2020
(* Linearization property based on [Thread] *)
2121
let lin_prop (seq_pref, cmds1, cmds2) =
2222
let sut = Spec.init () in
23-
let obs1, obs2 = ref [], ref [] in
23+
let obs1, obs2 = ref (Ok []), ref (Ok []) in
2424
let pref_obs = interp_plain sut seq_pref in
2525
let wait = ref true in
26-
let th1 = Thread.create (fun () -> while !wait do Thread.yield () done; obs1 := interp_thread sut cmds1) () in
27-
let th2 = Thread.create (fun () -> wait := false; obs2 := interp_thread sut cmds2) () in
26+
let th1 = Thread.create (fun () -> while !wait do Thread.yield () done; obs1 := try Ok (interp_thread sut cmds1) with exn -> Error exn) () in
27+
let th2 = Thread.create (fun () -> wait := false; obs2 := try Ok (interp_thread sut cmds2) with exn -> Error exn) () in
2828
Thread.join th1;
2929
Thread.join th2;
3030
Spec.cleanup sut;
31+
let obs1 = match !obs1 with Ok v -> ref v | Error exn -> raise exn in
32+
let obs2 = match !obs2 with Ok v -> ref v | Error exn -> raise exn in
3133
let seq_sut = Spec.init () in
3234
(* we reuse [check_seq_cons] to linearize and interpret sequentially *)
3335
check_seq_cons pref_obs !obs1 !obs2 seq_sut []
File renamed without changes.

test/cleanup_stm.ml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
open QCheck
2+
open STM
3+
4+
exception Cleanup_without_init
5+
exception Already_cleaned
6+
exception Random_postcond_failure
7+
8+
type status = Inited | Cleaned
9+
10+
let status = ref None (* global ref to keep track of cleanup/init status *)
11+
12+
(** This is a variant of refs to test for missing and double cleanup *)
13+
14+
module RConf =
15+
struct
16+
17+
type cmd =
18+
| Get
19+
| Set of int
20+
| Add of int [@@deriving show { with_path = false }]
21+
22+
let gen_cmd =
23+
let int_gen = Gen.nat in
24+
(Gen.oneof
25+
[Gen.return Get;
26+
Gen.map (fun i -> Set i) int_gen;
27+
Gen.map (fun i -> Add i) int_gen;
28+
])
29+
let arb_cmd _ = make ~print:show_cmd gen_cmd
30+
31+
type state = int
32+
33+
let init_state = 0
34+
35+
let next_state c s = match c with
36+
| Get -> s
37+
| Set i -> i
38+
| Add i -> s+i
39+
40+
type sut = int ref
41+
42+
let init_sut () =
43+
assert (!status = None || !status = Some Cleaned);
44+
status := Some Inited;
45+
ref 0
46+
47+
let cleanup _ = match !status with
48+
| None -> raise Cleanup_without_init
49+
| Some Cleaned -> raise Already_cleaned
50+
| Some Inited -> status := Some Cleaned
51+
52+
let run c r = match c with
53+
| Get -> Res (int, !r)
54+
| Set i -> Res (unit, (r:=i))
55+
| Add i -> Res (unit, let old = !r in r := i + old) (* buggy: not atomic *)
56+
57+
let precond _ _ = true
58+
59+
let postcond c (s:state) res = match c,res with
60+
| Get, Res ((Int,_),r) -> if r>70 then raise Random_postcond_failure; r = s
61+
| Set _, Res ((Unit,_),_)
62+
| Add _, Res ((Unit,_),_) -> true
63+
| _,_ -> false
64+
end
65+
66+
module RT_seq = STM_sequential.Make(RConf)
67+
module RT_dom = STM_domain.Make(RConf)
68+
69+
let rand = Random.State.make_self_init ()
70+
let i = ref 0
71+
;;
72+
for _i=1 to 250 do
73+
try
74+
Test.check_exn ~rand (RT_seq.agree_test ~count:1000 ~name:"STM ensure cleanup test sequential")
75+
with _e -> incr i; assert (!status = Some Cleaned);
76+
done;
77+
assert (!i = 250);
78+
Printf.printf "STM ensure cleanup: sequential test OK\n%!";
79+
(* reset things *)
80+
i := 0;
81+
status := None;
82+
for _i=1 to 100 do
83+
try
84+
Test.check_exn ~rand
85+
(Test.make ~count:1000 ~name:"STM ensure cleanup test parallel"
86+
(RT_dom.arb_cmds_triple 20 12) RT_dom.agree_prop_par) (* without retries *)
87+
with _e -> incr i; assert (!status = Some Cleaned);
88+
done;
89+
assert (!i = 100);
90+
Printf.printf "STM ensure cleanup: parallel test OK\n%!";

test/dune

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@
88

99

1010
(test
11-
(name cleanup)
12-
(modules cleanup)
11+
(name cleanup_lin)
12+
(modules cleanup_lin)
1313
(package qcheck-lin)
1414
(libraries qcheck-lin.domain)
1515
(preprocess (pps ppx_deriving.show ppx_deriving.eq))
1616
(action (run ./%{test} --verbose)))
1717

18+
(test
19+
(name cleanup_stm)
20+
(modules cleanup_stm)
21+
(package qcheck-stm)
22+
(libraries qcheck-stm.sequential qcheck-stm.domain)
23+
(preprocess (pps ppx_deriving.show ppx_deriving.eq))
24+
(action (run ./%{test} --verbose)))
25+
1826
(rule
1927
(enabled_if (= %{arch_sixtyfour} true))
2028
(action (copy mutable_set_v5.expected.64 mutable_set_v5.expected)))

0 commit comments

Comments
 (0)