Signals in Elixir
Here’s the translation of the Go code to Elixir, with explanations in Markdown format suitable for Hugo:
Elixir provides mechanisms to handle Unix signals, allowing programs to gracefully respond to events like termination requests or interrupts. Here’s how to handle signals in Elixir using the :os.signal/2
function and message passing.
defmodule SignalHandler do
def start do
# Register the process to receive SIGINT and SIGTERM signals
:os.set_signal(:sigint, :handle)
:os.set_signal(:sigterm, :handle)
# Print a message indicating we're waiting for a signal
IO.puts("awaiting signal")
# Start the signal handling loop
handle_signals()
end
defp handle_signals do
receive do
{:os_signal, signal} ->
IO.puts("\n#{signal}")
IO.puts("exiting")
end
end
end
# Start the signal handler
SignalHandler.start()
In Elixir, we use the :os.set_signal/2
function to register our process to receive specific signals. We’re interested in SIGINT
(interrupt) and SIGTERM
(termination) signals.
The handle_signals/0
function uses Elixir’s receive
block to wait for signal messages. When a signal is received, it’s printed, and then the program exits.
Unlike Go, Elixir doesn’t use channels for signal handling. Instead, it uses Erlang’s built-in message passing system. The operating system sends signals as messages to the registered process.
When we run this program, it will block waiting for a signal. By typing Ctrl+C
(which the terminal shows as ^C
), we can send a SIGINT
signal, causing the program to print the signal name and then exit.
$ elixir signals.exs
awaiting signal
^C
SIGINT
exiting
In this Elixir version, we’ve maintained the core functionality of the original Go program while adapting it to Elixir’s idioms and concurrency model. The program still waits for a signal and gracefully exits when one is received.