Skip to content

Commit 0d7b673

Browse files
committed
Address race condition
1 parent 6c3f308 commit 0d7b673

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

lib/mix/lib/mix/tasks/deps.partition.ex

+20-18
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,19 @@ defmodule Mix.Tasks.Deps.Partition do
7070
end
7171
end)
7272

73-
send_deps_and_server_loop(clients, [], deps, [])
73+
status = Map.new(deps, &{&1.app, :pending})
74+
send_deps_and_server_loop(clients, [], deps, status)
7475
end
7576

76-
defp send_deps_and_server_loop(available, busy, deps, completed) do
77-
{available, busy, deps} = send_deps(available, busy, deps, completed)
78-
server_loop(available, busy, deps, completed)
77+
defp send_deps_and_server_loop(available, busy, deps, status) do
78+
{available, busy, deps} = send_deps(available, busy, deps, status)
79+
server_loop(available, busy, deps, status)
7980
end
8081

81-
defp send_deps([client | available], busy, deps, completed) do
82-
case pop_with(deps, fn dep -> Enum.all?(dep.deps, &not_pending?(&1.app, deps, completed)) end) do
82+
defp send_deps([client | available], busy, deps, status) do
83+
case pop_with(deps, fn dep ->
84+
Enum.all?(dep.deps, &(Map.get(status, &1.app, :unknown) != :pending))
85+
end) do
8386
:error ->
8487
{[client | available], busy, deps}
8588

@@ -89,35 +92,34 @@ defmodule Mix.Tasks.Deps.Partition do
8992
end
9093

9194
:gen_tcp.send(client.socket, "#{dep.app}\n")
92-
send_deps(available, [client | busy], deps, completed)
95+
send_deps(available, [client | busy], deps, status)
9396
end
9497
end
9598

96-
defp send_deps([], busy, deps, _completed) do
99+
defp send_deps([], busy, deps, _status) do
97100
{[], busy, deps}
98101
end
99102

100-
defp not_pending?(app, deps, completed) do
101-
Keyword.has_key?(completed, app) or not Enum.any?(deps, &(&1.app == app))
102-
end
103-
104-
defp server_loop(available, _busy = [], _deps = [], completed) do
103+
defp server_loop(available, _busy = [], _deps = [], status) do
105104
shutdown_clients(available)
106-
Enum.any?(completed, &(elem(&1, 1) == true))
105+
Enum.any?(status, &(elem(&1, 1) == true))
107106
end
108107

109-
defp server_loop(available, busy, deps, completed) do
108+
defp server_loop(available, busy, deps, status) do
110109
receive do
111110
{:tcp, socket, data} ->
112-
[app, status] = data |> String.trim() |> String.split(":") |> Enum.map(&String.to_atom/1)
111+
[app, compiled?] =
112+
data |> String.trim() |> String.split(":") |> Enum.map(&String.to_atom/1)
113+
113114
deps = Enum.reject(deps, &(&1.app == app))
115+
status = Map.replace!(status, app, compiled?)
114116
{client, busy} = pop_with(busy, &(&1.socket == socket))
115117

116118
if Mix.debug?() do
117119
Mix.shell().info("-- mix deps.partition #{client.index} compiled #{app}")
118120
end
119121

120-
send_deps_and_server_loop([client | available], busy, deps, [{app, status} | completed])
122+
send_deps_and_server_loop([client | available], busy, deps, status)
121123

122124
{:tcp_closed, socket} ->
123125
shutdown_clients(available ++ busy)
@@ -134,7 +136,7 @@ defmodule Mix.Tasks.Deps.Partition do
134136
IO.write([Integer.to_string(index), "> ", data, terminator])
135137
end
136138

137-
server_loop(available, busy, deps, completed)
139+
server_loop(available, busy, deps, status)
138140
end
139141
end
140142

0 commit comments

Comments
 (0)