What are the differences between stopping a release with SIGINT and SIGTERM?

Hi,

After building a release with MIX_ENV=prod mix release, we are informed of the following:

# To stop it gracefully (you may also send SIGINT/SIGTERM)

What are the differences between stopping a release with SIGINT and SIGTERM?

SIGINT is supposed to be related to killing a process from inputting characters on the terminal. So if you CTRL+ C'd a process, that should send a SIGINT.

I think SIGTERM is a more of a “hey, let’s shut down this process gracefully” but this is meant to be triggered by another process, such as a process manager.

SIGKILL on the other hand is a non-graceful event. The OS won’t wait for your process to run any exit routines and will just kill it on the spot. That’s what happens when you run kill -9 on a process.

2 Likes
  • SIGINT - “Sorry to interrupt you, sir, but you need to come with Us.”
  • SIGTERM - “Your contract have been terminated, security will lead you out.”
  • SIGKILL - BAM!!!
6 Likes

Thank you @nickjanetakis

I am deploying a release with systemd and I have a choice to either send a SIGINT or a SIGTERM signal to stop the process.
I am asking the initial question because I do notice a difference between the 2 signals.

kill -s SIGINT $(_build/prod/rel/myapp/bin/myapp pid) gives:

BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution

kill -s SIGTERM $(_build/prod/rel/myapp/bin/myapp pid) gives:

:gen_event handler Logger.Backends.Console installed in Logger terminating
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol String.Chars not implemented for %{tag: :info_msg} of type Map. This protocol is implemented for the following type(s): Postgrex.Query, Postgrex.Copy, Decimal, Time, Float, BitString, Version.Requirement, Version, Atom, Date, URI, Integer, List, NaiveDateTime, DateTime
        (elixir 1.10.1) lib/string/chars.ex:3: String.Chars.impl_for!/1
        (elixir 1.10.1) lib/string/chars.ex:22: String.Chars.to_string/1
        (logger 1.10.1) lib/logger/formatter.ex:180: Logger.Formatter.metadata/1
        (logger 1.10.1) lib/logger/formatter.ex:152: anonymous fn/6 in Logger.Formatter.format/5
        (elixir 1.10.1) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
        (logger 1.10.1) lib/logger/formatter.ex:151: Logger.Formatter.format/5
        (logger 1.10.1) lib/logger/backends/console.ex:186: Logger.Backends.Console.format_event/5
        (logger 1.10.1) lib/logger/backends/console.ex:140: Logger.Backends.Console.log_event/5

Therefore, SIGTERM does not produce the same effect as with SIGINT.

Thank you @hauleth

Is there any documentation in Elixir that explains this with more in-depth technical details? I could not find any myself.

If you were in a terminal and hit CTRL + C inside of an iex session then you would get the same output as what you’re showing in your SIGINT output where you can pick what option to perform.

I suppose a better way to explain it then is a SIGINT will provide you the same outcome as if you were to have killed a process with CTRL + C. I updated my original reply to better reflect that.

I’m guessing the SIGTERM is what you want to have happen? That’s what I would send if I wanted to kill a process from another process.

That is the question I am having myself.

I want to stop the process as gracefully as possible so I would like to know how Elixir/Erlang reacts to such signals and choose what is best in my use case.

man 3 signal

And yes, you want SIGTERM.

This seems like bug in the Logger. Could you report it and I will check that out.

In general you want to use SIGTERM unless specified otherwise.

1 Like

Ok, I dug more and here is what I found:

On Unix systems, the Erlang runtime will interpret two types of signals.

SIGUSR1

    A SIGUSR1 signal forces a crash dump.
SIGTERM

    A SIGTERM will produce a stop message to the init process. This is equivalent to a init:stop/0 call.

    Introduced in ERTS 8.3 (Erlang/OTP 19.3)

source: https://erlang.org/doc/man/erl.html#signals

So I guess, that is the documentation I was looking for.

1 Like

Yes, I will do that.

Seems that it is already tracked there: https://github.com/elixir-lang/elixir/issues/9814

1 Like

For the record, migrating from Elixir 1.10.1 to 1.10.2 fixed the problem with the Logger.

3 Likes