I think the confusion results from understanding what a “shutdown” is.
Here’s one line where that confusion resides in the docs of Task.start/1:
If the current node is shutdown, the node will terminate even if the task was not completed
What is “the current node”? What makes the current node shutdown? What qualifies as a shutdown or not? How do you start a shutdown?
When you run iex -S mix you are starting and sustaining a vm node[0] that the Task child process resides in. So the spawned Task will continue to completion even after Foo.foo terminates. Compared to mix run -e Foo.foo which halts the vm node.
If you look at the docs of mix run you’ll see the --no-halt option. That’s because, by default, mix run halts the running system/node, which is different from a shutdown.
More details on what halt does from System.halt:
Terminates the Erlang runtime system without properly shutting down applications and ports. Please see
stop/1for a careful shutdown of the system.
So, I think the confusion here is understanding how a System/node starts and how a System/node stops.
Here’s a thread that may be of interest to you, to simulate a shutdown. In particular:
if you want to politely shutdown your system, you should invoke
:init.stop, which will recursively shutdown the supervision tree causingterminatecallbacks to be invoked
This is why in the docs it’s recommended to use Task.Supervisor as, I imagine, if you do a shutdown, it won’t take into account any outstanding Task.start processes.
[0] https://elixir-lang.org/getting-started/mix-otp/distributed-tasks.html




















