From 01c4c42e117636cdba2d5278c851fbe7a3b39bc0 Mon Sep 17 00:00:00 2001 From: Michal Muskala Date: Fri, 13 May 2016 20:51:08 +0200 Subject: Monitor owner of the connection The connection process should monitor the process that started it and die with the same reason that the owner process did. This should solve the issue of zombie connections laying around after the processes that started them die. --- lib/exirc/client.ex | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/exirc/client.ex') diff --git a/lib/exirc/client.ex b/lib/exirc/client.ex index cde4f1a..81a2f0a 100644 --- a/lib/exirc/client.ex +++ b/lib/exirc/client.ex @@ -32,7 +32,8 @@ defmodule ExIrc.Client do channels: [], debug?: false, retries: 0, - inet: :inet + inet: :inet, + owner: nil end ################# @@ -55,6 +56,7 @@ defmodule ExIrc.Client do """ @spec start_link(options :: list() | nil, process_opts :: list() | nil) :: {:ok, pid} | {:error, term} def start_link(options \\ [], process_opts \\ []) do + options = Keyword.put_new(options, :owner, self()) GenServer.start_link(__MODULE__, options, process_opts) end @doc """ @@ -285,17 +287,20 @@ defmodule ExIrc.Client do def init(options \\ []) do autoping = Keyword.get(options, :autoping, true) debug = Keyword.get(options, :debug, false) + owner = Keyword.fetch!(options, :owner) # Add event handlers handlers = Keyword.get(options, :event_handlers, []) |> List.foldl([], &do_add_handler/2) + ref = Process.monitor(owner) # Return initial state {:ok, %ClientState{ event_handlers: handlers, autoping: autoping, logged_on?: false, debug?: debug, - channels: ExIrc.Channels.init()}} + channels: ExIrc.Channels.init(), + owner: {owner, ref}}} end @doc """ Handle calls from the external API. It is not recommended to call these directly. @@ -497,6 +502,10 @@ defmodule ExIrc.Client do def handle_info({:ssl, socket, data}, state) do handle_info({:tcp, socket, data}, state) end + # If the owner process dies, we should die as well + def handle_info({:DOWN, ref, _, pid, reason}, %{owner: {pid, ref}} = state) do + {:stop, reason, state} + end # If an event handler process dies, remove it from the list of event handlers def handle_info({:DOWN, _, _, pid, _}, state) do handlers = do_remove_handler(pid, state.event_handlers) -- cgit v1.2.3