Terminate/2 function of a child process not called when doing application:stop

In our application we have the main app file event_store_app, which starts a top-level supervisor called event_store_sup:
start(_StartType, _StartArgs) -> event_store_sup:start_link().

The supervisor, intern, spawns 3 child processes, including one called persistence_store:

    ChildSpec_PS =
            {persistence_store, start_link, []},
    Children = [ChildSpec_ES, ChildSpec_SS, ChildSpec_PS],
    {ok, {RestartStrategy, Children}}.

In the persistence_store module, we have the terminate/2 function doing some test output:

terminate(_Reason, _State) ->
    FileName = "test_terminate.txt",
    Text = "Called",
    {ok, File} = file:open(FileName, [write]),
    file:write(File, Text),
    io:format("persistence_store:terminate being called!~n"),

The function is exported, and when doing our unit tests, we make sure that the persistence_store module is part of the supervision tree by making it crash on purpose, then calling some gen_server functions in it, confirming that it gets restarted by the supervisor.

However, when stopping our app with application:stop(event_store), the terminate/2 function of the child process is not called, even though the documentation suggests that the application stop call will be propagated through the supervision tree and call terminate/2 in all supervised processes.

What can be the reason here for the function not getting called?

Maybe 500ms is not enough to successfully finish terminate/2 because there are IO operations. Can you try increasing the timeout to e.g. 2000?

Already tried increasing it to 5000, and the terminate/2 function initially contained just the io:format.

Is your persistence_store process trapping exits? The documentation for gen_server:terminate/2 says:

If the gen_server process is part of a supervision tree and is ordered by its supervisor to terminate, this function is called with Reason=shutdown if the following conditions apply:

  • The gen_server process has been set to trap exit signals.

Appears to be ignoring the parameters and catching anything that would call terminate.

You lost me, what do you mean? :thinking: What parameters?

1 Like

Thank you! This was the solution.
Done by adding the following line in the init() function:

process_flag(trap_exit, true),

Sorry was my misunderstanding of what you meant by trapping signal exits. I thought you were talking about some value that would show up in the Reason parameter of terminate/2.