I writing an Elixir app with GenServer that starts an external application on boot and shuts it down and does other clean-up on exit. I've added bootup functionality in the init/1
callback and cleanup code in the terminate/2
callback.
The init
code works fine when the GenServer is started, and the terminate
method is also called when the :stop
signal is manually sent, but in the cases of unexpected shutdowns and interrupts (as in the case of hitting Ctrl+C) in IEx, the terminate code is not called.
Currently, I've gone over tons of forum threads, blog posts and documentation, including:
- Getting Started: GenServers
- Elixir-Lang-Talk: Graceful shutdown of GenServer(s) on exiting iex -S mix
- Elixir-Lang-Talk: Stopping Genserver vs Process.exit
From Elixir Docs - GenServers:
If the
GenServer
receives an exit signal (that is not:normal
) from any process when it is not trapping exits it will exit abruptly with the same reason and so not callterminate/2
. Note that a process does NOT trap exits by default and an exit signal is sent when a linked process exits or its node is disconnected.Therefore it is not guaranteed that
terminate/2
is called when aGenServer
exits. For such reasons, we usually recommend important clean-up rules to happen in separated processes either by use of monitoring or by links themselves.
but I have absolutely no idea how to get :init.stop
, linked processes
or anything else to work with this (since this is my first time with GenServers).
This is my code:
defmodule MyAwesomeApp do
use GenServer
def start do
GenServer.start_link(__MODULE__, nil)
end
def init(state) do
# Do Bootup stuff
IO.puts "Starting: #{inspect(state)}"
{:ok, state}
end
def terminate(reason, state) do
# Do Shutdown Stuff
IO.puts "Going Down: #{inspect(state)}"
:normal
end
end
MyAwesomeApp.start