I am trying to terminate whole supervision tree from a supervised worker process. Here is my supervision tree:
+--------------------------+
| |
+--------+ Sup1: Dynamic Supervisor +---------+
| | | |
| +-------------+------------+ |
| | |
| | |
v v v
+------------------+ +------------------+ +------------------+
| | | | | |
| Job1: Supervisor | | Job2: Supervisor | | Job3: Supervisor |
| | | | | |
+------------------+ +-+-------- +---+--+ +------------------+
| |
| |
| |
| |
v v
+-------------------+ +--------------+
| | | |
| Progress Monitor: | | Work: Worker |
| Worker | | |
| | +--------------+
+-------------------+
Process life cycle:
- A
Jobis started via:DynamicSupervisor.start_child(__MODULE__, spec) - Each job is a supervision tree as well: 1 supervisor (restart strategy -
one_for_one) -> 2 workers Progress Monitorworker knows when the given job is done- On job done,
Progress Monitorworker makes an attempt to terminate the whole job supervision tree, by calling:DynamicSupervisor.terminate_child(__MODULE__, pid) Progress Monitoris expected to do cleanup steps interminatecallback - it is trapping exit signals
Problems and observations:
DynamicSupervisor.terminate_childis a blocking call, which means it waits for all child processes to terminate as well, including the calling process -Progress MonitorProgress Monitoris in a deadlock and can not terminate. Parent supervisor sends:killsignal, which does not triggerterminatecallback
Quick workarounds:
Call
DynamicSupervisor.terminate_childfromProgress Monitorworker asynchronously:spawn(fn -> DynamicSupervisor.terminate_child(__MODULE__, pid) end)Define shutdown strategy for
Sup1: Dynamic Supervisor:shutdown: 5_000It will wait at most 5s for a job supervision tree termination and then it will send
shutdownexit signal. This will ensureterminatecallback being called forProgress Monitorprocess.
Not happy with both of them.
Questions:
- How to trigger supervision tree termination from a worker process and avoid deadlocks?
- If terminating supervision tree from a worker is not the best practice, what is the recommended way then?
- Any recommendations how to redesign supervision tree to make graceful termination easier?