How does IO.puts cause a "no process" exit?

The following code …

GenStage.sync_subscribe(cons, to: prod)

IO.puts "line 108"

# Wait for process to exit.
Process.monitor(cons)
receive do
  {:DOWN, _ref, :process, ^cons, :normal} ->
    :ok
  {:DOWN, _ref, :process, ^cons, reason} ->
    Process.exit(self, reason)
end

… crashes with ** (EXIT from #PID<0.672.0>) no process but only if the IO.puts call is present. If I comment it out, the code runs as intended and the corresponding tests pass.

Any ideas how that could be causing it?

1 Like

Answering my own question after further debugging: It looks like a race condition.

If I flip the order of IO.puts and Process.monitor, the crash goes away. So I suspect the consumer may be dying during the time IO.puts is running.

2 Likes