diff --git a/lib/file_system/backends/fs_inotify.ex b/lib/file_system/backends/fs_inotify.ex index 141682fbed2828e3e0aa90f9711c9dce339fc0ae..b673b50bc57c7c5e2db7bf4756cc37d2f90d18ce 100644 --- a/lib/file_system/backends/fs_inotify.ex +++ b/lib/file_system/backends/fs_inotify.ex @@ -41,6 +41,8 @@ defmodule FileSystem.Backends.FSInotify do {:spawn_executable, to_charlist(find_executable())}, [:stream, :exit_status, {:line, 16384}, {:args, port_args}, {:cd, System.tmp_dir!()}] ) + Process.link(port) + Process.flag(:trap_exit, true) {:ok, %{port: port, worker_pid: args[:worker_pid]}} end @@ -55,6 +57,11 @@ defmodule FileSystem.Backends.FSInotify do {:stop, :normal, state} end + def handle_info({:EXIT, port, _reason}, %{port: port}=state) do + send(state.worker_pid, {:backend_file_event, self(), :stop}) + {:noreply, state} + end + def handle_info(_, state) do {:noreply, state} end diff --git a/lib/file_system/backends/fs_mac.ex b/lib/file_system/backends/fs_mac.ex index f816f05247e7e9a11e14c85e71a2bfcf9caa6a09..65d39b71392f44278e660e92e09ab170f256cab5 100644 --- a/lib/file_system/backends/fs_mac.ex +++ b/lib/file_system/backends/fs_mac.ex @@ -45,6 +45,8 @@ defmodule FileSystem.Backends.FSMac do {:spawn_executable, to_charlist(find_executable())}, [:stream, :exit_status, {:line, 16384}, {:args, port_args}, {:cd, System.tmp_dir!()}] ) + Process.link(port) + Process.flag(:trap_exit, true) {:ok, %{port: port, worker_pid: args[:worker_pid]}} end @@ -59,6 +61,11 @@ defmodule FileSystem.Backends.FSMac do {:stop, :normal, state} end + def handle_info({:EXIT, port, _reason}, %{port: port}=state) do + send(state.worker_pid, {:backend_file_event, self(), :stop}) + {:noreply, state} + end + def handle_info(_, state) do {:noreply, state} end diff --git a/lib/file_system/backends/fs_windows.ex b/lib/file_system/backends/fs_windows.ex index 1242ebd66b3057ad4a4578c8d32c239e242a9013..89b1ecb909692a3688a4987d025cf4bae6d10b5a 100644 --- a/lib/file_system/backends/fs_windows.ex +++ b/lib/file_system/backends/fs_windows.ex @@ -40,6 +40,8 @@ defmodule FileSystem.Backends.FSWindows do {:spawn_executable, to_charlist(find_executable())}, [:stream, :exit_status, {:line, 16384}, {:args, port_args}, {:cd, System.tmp_dir!()}] ) + Process.link(port) + Process.flag(:trap_exit, true) {:ok, %{port: port, worker_pid: args[:worker_pid]}} end @@ -54,6 +56,11 @@ defmodule FileSystem.Backends.FSWindows do {:stop, :normal, state} end + def handle_info({:EXIT, port, _reason}, %{port: port}=state) do + send(state.worker_pid, {:backend_file_event, self(), :stop}) + {:noreply, state} + end + def handle_info(_, state) do {:noreply, state} end diff --git a/lib/file_system/worker.ex b/lib/file_system/worker.ex index f110770bc27a2bdbd1b72bd5e4509a04ec4eb52f..b771a6cf49b276d0ed3a19546a0169eb922ba3aa 100644 --- a/lib/file_system/worker.ex +++ b/lib/file_system/worker.ex @@ -25,7 +25,8 @@ defmodule FileSystem.Worker do end def handle_info({:DOWN, _pid, _, ref, _reason}, state) do - {:noreply, pop_in(state.subscribers[ref])} + subscribers = Map.drop(state.subscribers, [ref]) |> IO.inspect + {:noreply, %{state | subscribers: subscribers}} end def handle_info(_, state) do diff --git a/test/file_system_test.exs b/test/file_system_test.exs index d63d690fa6f7e8d910954da92b1e9bbf61ac339e..750b5d36c84b39246af3e2f2b83d21b510e5197f 100644 --- a/test/file_system_test.exs +++ b/test/file_system_test.exs @@ -1,13 +1,34 @@ defmodule FileSystemTest do use ExUnit.Case, async: true - test "subscribe api" do + test "file event api" do tmp_dir = System.cmd("mktemp", ["-d"]) |> elem(0) |> String.trim {:ok, pid} = FileSystem.start_link(dirs: [tmp_dir]) FileSystem.subscribe(pid) + :timer.sleep(200) File.touch("#{tmp_dir}/a") assert_receive {:file_event, ^pid, {_path, _events}}, 5000 + + new_subscriber = spawn(fn -> + FileSystem.subscribe(pid) + :timer.sleep(10000) + end) + assert Process.alive?(new_subscriber) + Process.exit(new_subscriber, :kill) + refute Process.alive?(new_subscriber) + + :timer.sleep(200) + File.touch("#{tmp_dir}/b") + assert_receive {:file_event, ^pid, {_path, _events}}, 5000 + + Port.list + |> Enum.reject(fn port -> + :undefined == port |> Port.info |> Access.get(:os_pid) + end) + |> Enum.each(&Port.close/1) + assert_receive {:file_event, ^pid, :stop}, 5000 + File.rm_rf!(tmp_dir) end end