Search code examples
networkingelixirgen-server

Elixir - Catching :enetunreach and :ehostunreach errors


I have a GenServer that creates a connection with a remote host every x seconds and I'm having a hard time catching network related errors (more specifically :enetunreach and :ehostunreach).

** (EXIT from #PID<0.327.0>) shell process exited with reason: :enetunreach
** (EXIT from #PID<0.327.0>) shell process exited with reason: :ehostunreach

The base code I'm working with looks basically like this:

try do
  # Create Connection
catch
  type, call ->
    IO.inspect("Something happened while trying to connect.")
    IO.inspect(type)
    IO.inspect(call)
end

Have already tried both catch and raise but it always takes everything down with these errors.


Solution

  • The most important thing you should have figured out, would be how processes do live in the OTP actor model. The process cannot interfere the behaviour of another process, including, but not limited to catching exceptions thrown/raised there.

    Consider the following contrived example, mimicking the issue you have.

    defmodule M do
      use GenServer  
      
      # @impl GenServer
      # def init(:ok), do: {:ok, Process.flag(:trap_exit, true)}
      # @impl GenServer
      # def handle_info({:EXIT, _pid, reason}, state),
      #   do: {:noreply, IO.inspect("CAUGHT!")}
      @impl GenServer
      def handle_call(:test, _from, state),
        do: {:reply, Process.exit(self(), :foo), state}
    end
    
    {:ok, pid} = GenServer.start_link M, :ok
    GenServer.call(pid, :test)
    

    Until you have the commented lines uncommented, you’ll get back somewhat like [error] GenServer #PID<0.132.0> terminating. The only possibility you have to control (not to control, actually, to supervise only) the flow of another process, is by monitoring it.

    That said, you need to monitor the process you start, set your process to trap exits and react accordingly to {:EXIT, _, _} message received.


    TL;DR try/1 would catch exceptions raised within the same process only.