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
GenServerreceives 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/2is called when aGenServerexits. 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