diff options
-rw-r--r-- | lib/exirc/client.ex | 13 | ||||
-rw-r--r-- | lib/exirc/exirc.ex | 2 | ||||
-rw-r--r-- | test/client_test.exs | 25 |
3 files changed, 34 insertions, 6 deletions
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) diff --git a/lib/exirc/exirc.ex b/lib/exirc/exirc.ex index cfa2654..72be33c 100644 --- a/lib/exirc/exirc.ex +++ b/lib/exirc/exirc.ex @@ -50,7 +50,7 @@ defmodule ExIrc do @spec start_client! :: {:ok, pid} | {:error, term} def start_client! do # Start the client worker - Supervisor.start_child(:exirc, []) + Supervisor.start_child(:exirc, [[owner: self()]]) end ############## diff --git a/test/client_test.exs b/test/client_test.exs index 6cff0b7..b7277b6 100644 --- a/test/client_test.exs +++ b/test/client_test.exs @@ -1,11 +1,30 @@ defmodule ExIrc.ClientTest do use ExUnit.Case - test "start multiple clients" do - {:ok, pid} = ExIrc.start_client! - {:ok, pid2} = ExIrc.start_client! + assert {:ok, pid} = ExIrc.start_client! + assert {:ok, pid2} = ExIrc.start_client! assert pid != pid2 end + test "client dies if owner process dies" do + test_pid = self() + + pid = spawn_link(fn -> + assert {:ok, pid} = ExIrc.start_client! + send(test_pid, {:client, pid}) + receive do + :stop -> :ok + end + end) + + client_pid = receive do + {:client, pid} -> pid + end + + assert Process.alive?(client_pid) + send(pid, :stop) + :timer.sleep(1) + refute Process.alive?(client_pid) + end end |