[Proposal] In DynamicSupervisor, process terminations asynchronously.

201 views
Skip to first unread message

Derek Kraan

unread,
Jan 15, 2019, 5:29:54 AM1/15/19
to elixir-lang-core
Currently, a call to DynamicSupervisor.terminate_child waits until the process has exited (or the shutdown times out) before processing any other messages. This can take up to `shutdown` milliseconds, which could be a long time depending on what the application has configured.

I have run into this problem before in my work, and solved it in my project by ensuring that a process is in a "ready to terminate" state before asking the DynamicSupervisor to terminate it. This works for us, but we have to be really careful with this and if we make a mistake it could have a huge performance impact.

After reading the code, I think it is possible to process these terminations asynchronously. This would allow other work (including process restarts, starting new processes, terminating other processes) to continue unimpeded.

The downside is that the DynamicSupervisor would get more complex. The upside is that we could solve a potentially big performance bottleneck in people's apps.

Is this a change that would be considered?

José Valim

unread,
Jan 15, 2019, 6:17:14 AM1/15/19
to elixir-l...@googlegroups.com
The option here is generally to signal the worker/child to terminate and make sure it has a proper restart: value so the supervisor does not restart it once it exits. This is the best option because it also won't block the supervisor.


José Valim
Skype: jv.ptec
Founder and Director of R&D


--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/0bab277d-588e-4901-ba82-fe82375db301%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Louis Pilfold

unread,
Jan 15, 2019, 6:20:37 AM1/15/19
to elixir-l...@googlegroups.com
Hi Derek

Why not spawn a new process and call DynamicSupervisor.terminate_child from there? Perhaps using the Task module.

For me this would be preferable to making an async version of the function as (in addition to keeping the DynamicSupervisor API simple) it leaves it up to the caller to decide how the timeout should handled (should we crash, retry, or discard the error?), and whether there should be a notification of some kind when the call has succeeded.

Cheers,
Louis

--

Derek Kraan

unread,
Jan 15, 2019, 6:37:34 AM1/15/19
to elixir-l...@googlegroups.com
To clarify, the issue is not that the call to `DynamicSupervisor.terminate_child` is synchronous, the issue is that the dynamic supervisor itself cannot process any other messages while processing the termination. With a `:no_reply` return tuple in handle_call it would be possible to reply at a later time when the process(es) have exited, and the dynamic supervisor could continue to process other messages in the meantime.

Signalling the child to terminate and using `:transient` restart type might be a good option for us, although it does feel weird to me that `terminate_child` has such a huge gotcha that the advice is to not use it.

I should also note that `Supervisor` has the exact same behaviour and gotcha, although `DynamicSupervisor` does already diverge from `Supervisor` in terms of behaviour (eg, starting and terminating processes concurrently instead of in order).

Reply all
Reply to author
Forward
0 new messages