diff --git a/src/proper_statem.erl b/src/proper_statem.erl
index 96794985..36eacc90 100644
--- a/src/proper_statem.erl
+++ b/src/proper_statem.erl
@@ -603,7 +603,8 @@ safe_apply(M, F, A) ->
%% concurrent tasks.
%%
`Result' specifies the outcome of the attemp to serialize command
%% execution, based on the results observed. It can be one of the following:
-%% - `ok'
- `no_possible_interleaving'
+%% - `ok'
- `no_possible_interleaving'
+%% - `{exception, Kind, Reason, StackTrace}'
%%
-spec run_parallel_commands(mod_name(), parallel_testcase()) ->
@@ -622,28 +623,42 @@ run_parallel_commands(Mod, {Sequential, Parallel}, Env) ->
case run(Mod, Sequential, Env) of
{{Seq_history, State, ok}, SeqEnv} ->
F = fun(T) -> execute(T, SeqEnv, Mod) end,
- Parallel_history = pmap(F, Parallel),
+ case pmap(F, Parallel) of
+ {ok, Parallel_history} ->
case check(Mod, State, SeqEnv, false, [], Parallel_history) of
true ->
{Seq_history, Parallel_history, ok};
false ->
{Seq_history, Parallel_history, no_possible_interleaving}
end;
+ {error, Exc, Parallel_history} ->
+ {Seq_history, Parallel_history, Exc}
+ end;
{{Seq_history, _, Res}, _} ->
{Seq_history, [], Res}
end.
%% @private
-spec execute(command_list(), proper_symb:var_values(), mod_name()) ->
- parallel_history().
-execute([], _Env, _Mod) -> [];
-execute([{set, {var,V}, {call,M,F,A}} = Cmd|Rest], Env, Mod) ->
+ {ok, parallel_history()} | {error, any, parallel_history()}.
+execute(Cmds, Env, Mod) -> execute(Cmds, Env, Mod, []).
+
+-spec execute(command_list(), proper_symb:var_values(), mod_name(),
+ parallel_history()) -> {ok, parallel_history()} |
+ {error, proper:exception(), parallel_history()}.
+execute([], _Env, _Mod, Hist) -> {ok,lists:reverse(Hist)};
+execute([{set, {var,V}, {call,M,F,A}} = Cmd|Rest], Env, Mod, Hist) ->
M2 = proper_symb:eval(Env, M),
F2 = proper_symb:eval(Env, F),
A2 = proper_symb:eval(Env, A),
- Res = apply(M2, F2, A2),
+
+ case safe_apply(M2, F2, A2) of
+ {ok,Res} ->
Env2 = [{V,Res}|Env],
- [{Cmd,Res}|execute(Rest, Env2, Mod)].
+ execute(Rest, Env2, Mod, [{Cmd,Res}|Hist]);
+ {error, Exc} ->
+ {error, Exc, lists:reverse(Hist)}
+ end.
-spec pmap(fun((command_list()) -> parallel_history()), [command_list()]) ->
[parallel_history()].
@@ -654,18 +669,28 @@ pmap(F, L) ->
[command_list()]) -> [pid()].
spawn_jobs(F, L) ->
Parent = self(),
- [spawn_link_cp(fun() -> Parent ! {self(),catch {ok,F(X)}} end) || X <- L].
-
--spec await([pid()]) -> [parallel_history()].
-await([]) -> [];
-await([H|T]) ->
+ [spawn_link_cp(fun() -> Parent ! {self(), F(X)} end) || X <- L].
+
+-spec await([pid()]) ->
+ {ok, [parallel_history()]} |
+ {error, proper:exception(), [parallel_history()]}.
+await(Pids) -> await(Pids, [], false).
+
+-spec await([pid()], [parallel_history()], false | proper:exception()) ->
+ {ok, [parallel_history()]} |
+ {error, proper:exception(), [parallel_history()]}.
+await([], Hist, false) -> {ok, lists:reverse(Hist)};
+await([], Hist, Exc) -> {error, Exc, lists:reverse(Hist)};
+await([H|T], Hist, MaybeExc) ->
receive
{H, {ok, Res}} ->
- [Res|await(T)];
- {H, {'EXIT',_} = Err} ->
- _ = [exit(Pid, kill) || Pid <- T],
- _ = [receive {P,_} -> d_ after 0 -> i_ end || P <- T],
- erlang:error(Err)
+ await(T, [Res|Hist], MaybeExc);
+ {H, {error, Exc, Res}} ->
+ Exc2 = case MaybeExc of
+ false -> Exc;
+ E -> E
+ end,
+ await(T, [Res|Hist], Exc2)
end.
%% @private