Elixir task await is not exiting the task o timeout

So according to the Elixir task documentation If the timeout is exceeded, then the current process will exit. If the task process is linked to the current process which is the case when a task is started with async, then the task process will also exit.

So I did the following in iex terminal:

t  = Task.async(fn -> Process.sleep(30_000)end) 
Task.await(t) 

I received the following error

** (exit) exited in: Task.await(%Task{owner: #PID<0.239.0>, pid: #PID<0.259.0>, ref: #Reference<0.4061026072.3515088903.77992>}, 5000)
    ** (EXIT) time out
    (elixir 1.10.3) lib/task.ex:607: Task.await/2

But however when I do the following:

%Task{pid: pid} = t 
Process.alive?(pid)

I get true. Shouldn’t I be getting false because the documentation says that await should exit the task process if timeout is exceeded.

Hmm… agree this sounds rather confusing, because if we wait for another 25 sec and then try Process.alive?(pid) again it will return false.

I’m looking at the source and see elixir/task.ex at v1.11.4 · elixir-lang/elixir · GitHub that, indeed, after timeout it just demonitors task process and exists caller (that very exit that you showed)

I think the iex process is doing some special things - trying this with a nested Task gives a very different result:

Interactive Elixir (1.11.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> t = Task.async(fn -> Task.async(fn -> Process.sleep(30000); end) |> IO.inspect() |> Task.await() end)
%Task{
  owner: #PID<0.108.0>,
  pid: #PID<0.109.0>,
  ref: #Reference<0.2364364556.505413638.7780>
}
%Task{
  owner: #PID<0.106.0>,
  pid: #PID<0.108.0>,
  ref: #Reference<0.2364364556.505413638.7778>
}
iex(2)> 
22:24:44.313 [error] Task #PID<0.108.0> started from #PID<0.106.0> terminating
** (stop) exited in: Task.await(%Task{owner: #PID<0.108.0>, pid: #PID<0.109.0>, ref: #Reference<0.2364364556.505413638.7780>}, 5000)
    ** (EXIT) time out
    (elixir 1.11.4) lib/task.ex:643: Task.await/2
    (elixir 1.11.4) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (elixir 1.11.4) lib/task/supervised.ex:35: Task.Supervised.reply/5
    (stdlib 3.14.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<45.79398840/0 in :erl_eval.expr/5>
    Args: []
** (EXIT from #PID<0.106.0>) shell process exited with reason: exited in: Task.await(%Task{owner: #PID<0.108.0>, pid: #PID<0.109.0>, ref: #Reference<0.2364364556.505413638.7780>}, 5000)
    ** (EXIT) time out
        
Interactive Elixir (1.11.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Process.alive?(t.pid)
** (CompileError) iex:1: undefined function t/0
    (stdlib 3.14.2) lists.erl:1358: :lists.mapfoldl/3

The outer Task calls Task.await, and exits after the timeout. That exit is passed to the linked Task that’s sleeping.

This also restarts the iex process (!) so variables like t are lost.

Thanks for the reply. So you mean to say that the iex shell process is somehow acting differently and running it inside another process would actually lead to expected results ?