Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.2] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.4 (603602e) (compiled with Erlang/OTP 28)
Operating system
any
Current behavior
Consider this code:
defmodule LeakCollectable do
defstruct []
end
defimpl Collectable, for: LeakCollectable do
def into(_original) do
collector = fn
acc, {:cont, elem} ->
new_acc = acc ++ [elem]
Process.put(:trace, [{:cont, acc, elem, new_acc} | Process.get(:trace, [])])
new_acc
acc, :done ->
Process.put(:done_acc, acc)
acc
acc, :halt ->
Process.put(:halt_acc, acc)
acc
end
{[:initial], collector}
end
end
Process.put(:trace, [])
try do
for x <- [1, 2, 3], into: %LeakCollectable{} do
if x == 3, do: raise("boom")
x
end
rescue
_ -> :ok
end
Result:
IO.inspect(Enum.reverse(Process.get(:trace)))
[
{:cont, [:initial], 1, [:initial, 1]},
{:cont, [:initial, 1], 2, [:initial, 1, 2]}
]
IO.inspect(Process.get(:halt_acc))
[:initial]
Note that final invocation was passed the initial accumulator possibly leading to resource leak or unaccounted for side effects
The bug is in
|
build_into(Ann, Clauses, Expr, Into, Uniq, S) -> |
The
build_reduce passes
Acc as the initial value, but internally creates a new variable for the evolving accumulator. Then in
stacktrace_clause the original
Acc is used
Expected behavior
Collectable halt invoked with final accumulator value
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.2] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.4 (603602e) (compiled with Erlang/OTP 28)
Operating system
any
Current behavior
Consider this code:
Result:
Note that final invocation was passed the initial accumulator possibly leading to resource leak or unaccounted for side effects
The bug is in
elixir/lib/elixir/src/elixir_erl_for.erl
Line 168 in b7a832e
The
build_reducepassesAccas the initial value, but internally creates a new variable for the evolving accumulator. Then instacktrace_clausethe originalAccis usedExpected behavior
Collectable
haltinvoked with final accumulator value