Exception raised on normal exit

Hello everyone.

I have a GenServer process that is responsible for sending push notitifications to mobile devices when the user receives a message. To prevent multiple messages going out within a very short period of time, the GenServer times out after five seconds of inactivity. It (re)sets a timer following a handle_call that indicates another message was sent:

def handle_call({:unread_count_changed, opts, process}, _, %{timer: timer}) do
  Process.cancel_timer(state.timer)
  # Do some work...
  timer = process.send_after(self(), {:send_push_notifications, opts}, 5000)
  {:reply, nil, %{state | timer: timer}}
end

When the timer finally times out, it will send a message to itself to terminate. In the handle_info that does this, I respond with {:stop, :normal, state}:

def handle_info({:send_push_notifications, opts}, state) do
  # Send push notifications...
  {:stop, :normal, state}
end

This works fine most of the time, but sometimes it will cause an error to be thrown:

Process #PID<0.534.0> terminating: {{:normal, {GenServer, :call, [{:via, Registry, {:user_notifier, "42"}}]}}}

I though normal exits were not supposed to throw an error. Why am I seeing this?

Thanks!

Normal exit is an exit with reason :normal - here you have a tuple. This tuple is produced probably in the process that call GenServer.call, but the gen server exits during the call before returning the response. This is a crash for the caller, since it will never receive a response.

1 Like

Thanks! I was indeed looking in the wrong place and the issue was occurring in the calling code. It’s been fixed now.