dc0d
Stale/Deadlock Process
Assume there is a function like:
def sample do
lab_pid = self()
spawn_link(fn ->
spawn_link(fn ->
Process.flag(:trap_exit, true)
receive do
{:EXIT, _pid, :normal} ->
send(lab_pid, :done)
end
end)
:timer.sleep(100)
end)
receive do
msg ->
msg
end
end
This works. But if we remove the sleep, it becomes stale/deadlock. Why?
Most Liked
sasajuric
I wouldn’t call it a deadlock, but rather a race condition. Too see why it happens, let’s first name these processes:
def sample do
# process A
lab_pid = self()
spawn_link(fn ->
# process B
spawn_link(fn ->
# process C
Process.flag(:trap_exit, true)
receive do
{:EXIT, _pid, :normal} ->
send(lab_pid, :done)
end
end)
end)
receive do
msg ->
msg
end
end
So without a timeout, it’s possible that process B stops before Process.flag in process C has been invoked. This happens because spawn and spawn_link are asynchronous. When these functions return, the process has been created, but it’s possible that they still haven’t executed any instruction.
So in this scenario, if process C starts trapping exits after process B had stopped, the corresponding exit signal won’t be converted into a message. So now, you have process C waiting forever for a message which will never arrive, and consequently, process A is also waiting forever for a message which process C will never send.
The solution would be to use synchronous start, e.g. with :proc_lib:
def sample do
lab_pid = self()
spawn_link(fn ->
:proc_lib.start_link(Kernel, :apply, [fn ->
Process.flag(:trap_exit, true)
# `:proc_lib.start_link` will return after this function is invoked
:proc_lib.init_ack({:ok, self()})
receive do
{:EXIT, _pid, :normal} ->
send(lab_pid, :done)
end
end, []])
end)
receive do
msg ->
msg
end
end
sasajuric
OvermindDL1
Last Post!
OvermindDL1
Oh yes, that, I was reading it as the other way (that the parent would die when it’s the parent calling monitor on the child)! Yes, that is why monitor’s should be used, they are always ‘safe’, you will always receive a message of :DOWN, even if it went down before the monitor was started. Monitors are much better than links for watching process lifetimes, links should only be used to actually link and die.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









