Skip to content

Commit d6edbc6

Browse files
committed
Fix for run_parallel_commands not handling command crash
1 parent c932eef commit d6edbc6

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

src/proper_statem.erl

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ safe_apply(M, F, A) ->
603603
%% concurrent tasks.</li>
604604
%% <li>`Result' specifies the outcome of the attemp to serialize command
605605
%% execution, based on the results observed. It can be one of the following:
606-
%% <ul><li> `ok' </li><li> `no_possible_interleaving' </li></ul> </li>
606+
%% <ul><li> `ok' </li><li> `no_possible_interleaving' </li>
607+
%% <li> `{exception, Kind, Reason, StackTrace}' </li></ul> </li>
607608
%% </ul>
608609

609610
-spec run_parallel_commands(mod_name(), parallel_testcase()) ->
@@ -622,28 +623,42 @@ run_parallel_commands(Mod, {Sequential, Parallel}, Env) ->
622623
case run(Mod, Sequential, Env) of
623624
{{Seq_history, State, ok}, SeqEnv} ->
624625
F = fun(T) -> execute(T, SeqEnv, Mod) end,
625-
Parallel_history = pmap(F, Parallel),
626+
case pmap(F, Parallel) of
627+
{ok, Parallel_history} ->
626628
case check(Mod, State, SeqEnv, false, [], Parallel_history) of
627629
true ->
628630
{Seq_history, Parallel_history, ok};
629631
false ->
630632
{Seq_history, Parallel_history, no_possible_interleaving}
631633
end;
634+
{error, Exc, Parallel_history} ->
635+
{Seq_history, Parallel_history, Exc}
636+
end;
632637
{{Seq_history, _, Res}, _} ->
633638
{Seq_history, [], Res}
634639
end.
635640

636641
%% @private
637642
-spec execute(command_list(), proper_symb:var_values(), mod_name()) ->
638-
parallel_history().
639-
execute([], _Env, _Mod) -> [];
640-
execute([{set, {var,V}, {call,M,F,A}} = Cmd|Rest], Env, Mod) ->
643+
{ok, parallel_history()} | {error, any, parallel_history()}.
644+
execute(Cmds, Env, Mod) -> execute(Cmds, Env, Mod, []).
645+
646+
-spec execute(command_list(), proper_symb:var_values(), mod_name(),
647+
parallel_history()) -> {ok, parallel_history()} |
648+
{error, proper:exception(), parallel_history()}.
649+
execute([], _Env, _Mod, Hist) -> {ok,lists:reverse(Hist)};
650+
execute([{set, {var,V}, {call,M,F,A}} = Cmd|Rest], Env, Mod, Hist) ->
641651
M2 = proper_symb:eval(Env, M),
642652
F2 = proper_symb:eval(Env, F),
643653
A2 = proper_symb:eval(Env, A),
644-
Res = apply(M2, F2, A2),
654+
655+
case safe_apply(M2, F2, A2) of
656+
{ok,Res} ->
645657
Env2 = [{V,Res}|Env],
646-
[{Cmd,Res}|execute(Rest, Env2, Mod)].
658+
execute(Rest, Env2, Mod, [{Cmd,Res}|Hist]);
659+
{error, Exc} ->
660+
{error, Exc, lists:reverse(Hist)}
661+
end.
647662

648663
-spec pmap(fun((command_list()) -> parallel_history()), [command_list()]) ->
649664
[parallel_history()].
@@ -654,18 +669,28 @@ pmap(F, L) ->
654669
[command_list()]) -> [pid()].
655670
spawn_jobs(F, L) ->
656671
Parent = self(),
657-
[spawn_link_cp(fun() -> Parent ! {self(),catch {ok,F(X)}} end) || X <- L].
658-
659-
-spec await([pid()]) -> [parallel_history()].
660-
await([]) -> [];
661-
await([H|T]) ->
672+
[spawn_link_cp(fun() -> Parent ! {self(), F(X)} end) || X <- L].
673+
674+
-spec await([pid()]) ->
675+
{ok, [parallel_history()]} |
676+
{error, proper:exception(), [parallel_history()]}.
677+
await(Pids) -> await(Pids, [], false).
678+
679+
-spec await([pid()], [parallel_history()], false | proper:exception()) ->
680+
{ok, [parallel_history()]} |
681+
{error, proper:exception(), [parallel_history()]}.
682+
await([], Hist, false) -> {ok, lists:reverse(Hist)};
683+
await([], Hist, Exc) -> {error, Exc, lists:reverse(Hist)};
684+
await([H|T], Hist, MaybeExc) ->
662685
receive
663686
{H, {ok, Res}} ->
664-
[Res|await(T)];
665-
{H, {'EXIT',_} = Err} ->
666-
_ = [exit(Pid, kill) || Pid <- T],
667-
_ = [receive {P,_} -> d_ after 0 -> i_ end || P <- T],
668-
erlang:error(Err)
687+
await(T, [Res|Hist], MaybeExc);
688+
{H, {error, Exc, Res}} ->
689+
Exc2 = case MaybeExc of
690+
false -> Exc;
691+
E -> E
692+
end,
693+
await(T, [Res|Hist], Exc2)
669694
end.
670695

671696
%% @private

0 commit comments

Comments
 (0)