I have this code which is a basic OTP server:
defmodule Clients do
use Application
require Logger
def stuff do
Logger.debug "Clients.start/0"
# {:ok, pid} = Task.Supervisor.start_child(Clients.TaskSupervisor, fn -> doclient end)
end
def doclient(port) do
Logger.debug "Clients.doclient/0"
{:ok, socket} = :gen_tcp.listen(port,[:binary, packet: :line, active: false, reuseaddr: true])
#if this is under 2000ms there the process exits with a shutdown error
:timer.sleep(1500)
end
def start(_type, _args) do
import Supervisor.Spec
Logger.debug "Clients.init/1"
children = [
supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]),
worker(Task, [Clients, :doclient, [4040]])
]
opts = [strategy: :one_for_one, name: Clients.Supervisor]
Supervisor.start_link(children, opts)
end
end
The output from iex is:
iex(1)> Clients.start(1,2)
20:07:19.879 [debug] Clients.init/1
20:07:19.889 [debug] Clients.doclient/0
{:ok, #PID<0.141.0>}
iex(2)>
20:07:21.402 [debug] Clients.doclient/0
20:07:22.909 [debug] Clients.doclient/0
20:07:24.413 [debug] Clients.doclient/0
** (EXIT from #PID<0.139.0>) shutdown
If the doclient/1 timer call is under 2 seconds the above shutdown occurs but otherwise it ticks away happily. I'm not sure why? If I want doclient/1 to execute some arbitrary code that will take less than 2 seconds (which is not I imagine a reliable period anyway) this call will always explode.
You are using Task as your worker. So what happens is that once Task wakes up from the sleep it finishes its work and that process goes away. In your supervisor spec you are requesting:
children = [
supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]),
worker(Task, [Clients, :doclient, [4040]])
]
opts = [strategy: :one_for_one, name: Clients.Supervisor]
Supervisor.start_link(children, opts)
which tells OTP to restart your worker if it finishes or goes away in any way. So after 1.5 seconds (your time to sleep) the supervisor starts another task. It does this 3 times in the span of 5 seconds.
Supervisor.start_link has default options that specify intensity of restarts. Per the docs on Supervisor.Spec.supervise/2, the defaults are max 3 restarts in 5 seconds. That is why your supervisor shuts down with sleep time of 1.5 seconds and happily keeps on going with interval of 2 seconds.
All in all I think you need to rethink the use of tasks in this supervision tree. It is impossible to guess what fits best for your use case since you did not mention what it is.
HTH