Skip to content

Commit

Permalink
Fix riak_core_util:pmap/2 infinite stall
Browse files Browse the repository at this point in the history
This commit changes riak_core_util:pmap/2 to use spawn_link rather
than spawn to create the asynchronous processes. Without this change,
pmap/2 can stall forever if any of these processes crashes -- eg. by
using a map function that generates an error.

This commit also fixes the function -spec as well as optimizes the
final stage of the pmap by using a list comprehension rather than
lists:unzip (this is faster and generates less garbage).
  • Loading branch information
jtuple committed Jun 11, 2014
1 parent e08fe59 commit db8a28c
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions src/riak_core_util.erl
Expand Up @@ -300,19 +300,22 @@ ensure_started(App) ->

%% @doc Invoke function `F' over each element of list `L' in parallel,
%% returning the results in the same order as the input list.
-spec pmap(function(), [node()]) -> [any()].
-spec pmap(F, L1) -> L2 when
F :: fun((A) -> B),
L1 :: [A],
L2 :: [B].
pmap(F, L) ->
Parent = self(),
lists:foldl(
fun(X, N) ->
spawn(fun() ->
Parent ! {pmap, N, F(X)}
end),
spawn_link(fun() ->
Parent ! {pmap, N, F(X)}
end),
N+1
end, 0, L),
L2 = [receive {pmap, N, R} -> {N,R} end || _ <- L],
{_, L3} = lists:unzip(lists:keysort(1, L2)),
L3.
L3 = lists:keysort(1, L2),
[R || {_,R} <- L3].

-record(pmap_acc,{
mapper,
Expand Down

0 comments on commit db8a28c

Please sign in to comment.