I have a two part question concerning a module like so:
defmodule AsyncAwait do
defp long_running_task(id) do
Process.sleep(5_000)
IO.puts("Completed #{id}")
{:ok, "Completed #{id}"}
end
def perform_tasks(task_ids \\ [0, 1, 2]) do
task_ids
|> Enum.map(fn id ->
Task.async(fn ->
long_running_task(id)
end)
end)
|> Enum.map(fn task ->
IO.inspect(self())
Task.await(task, 1_000)
end)
end
end
When I launch the iex
shell and run AsyncAwait.perform_tasks()
, I recieve a timeout and an exit as expected, at the await:
** (exit) exited in: Task.await(%Task{owner: #PID<0.151.0>, pid: #PID<0.153.0>, ref: #Reference<0.3029894714.2600271873.129496>}, 1000)
** (EXIT) time out
(elixir 1.13.4) lib/task.ex:809: Task.await/2
(elixir 1.13.4) lib/enum.ex:1593: Enum."-map/2-lists^map/1-0-"/2
I would expect that this kills the caller process, and hence also all the associated task processes that were spawned during the async call. This is what the docs say:
A timeout, in milliseconds or
:infinity
, can be given with a default value of5000
. If the timeout is exceeded, then the caller process will exit. If the task process is linked to the caller process which is the case when a task is started withasync
, then the task process will also exit. If the task process is trapping exits or not linked to the caller process, then it will continue to run - Task — Elixir v1.13.4
- Normally when the caller process exits, I expected it would kill the
iex
shell since they exist in the same process. I can verify that they exist in the same process since I callIO.inspect(self())
in the anonymous function that executes theTask.await
, and when comparing it to the output of callingself()
iniex
, they are both indeed the same.
However the iex
prompt numbers do not reset after the error, and its pid does not change either. Manually killing the current process using Process.exit(self(), :exit)
resets the iex
prompt number and the pid
of the iex process, so I suspect that the caller process is not actually being killed. If it isn’t then what process actually exits due to the timeout?
- After 5 seconds I still see the output from the tasks in the
iex
shell:
Completed 0
Completed 1
Completed 2
This indicates that the async tasks that were spawned are still running.
How could this be happening? Assuming the caller processes did actually exit this means the associated task processes did not exit, which contradict the docs above.