Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions lib/ex_cmd/log.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule ExCmd.Log do
@moduledoc false

require Logger

@spec debug(String.t(), keyword) :: :ok
def debug(msg, opts \\ []) do
if Application.get_env(:ex_cmd, :enable_debug_logs) do
Logger.debug(msg, opts)
else
:ok
end
end

@spec error(String.t(), keyword) :: :ok
def error(msg, opts \\ []) do
Logger.error(msg, opts)
end
end
21 changes: 10 additions & 11 deletions lib/ex_cmd/process.ex
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,13 @@ defmodule ExCmd.Process do

use GenServer

alias ExCmd.Log
alias ExCmd.Process.Exec
alias ExCmd.Process.Operations
alias ExCmd.Process.Pipe
alias ExCmd.Process.Proto
alias ExCmd.Process.State

require Logger

defmodule Error do
defexception [:message]
end
Expand Down Expand Up @@ -579,7 +578,7 @@ defmodule ExCmd.Process do

@impl true
def handle_cast({:prepare_exit, caller, timeout}, state) do
Logger.debug("prepare_exit: #{timeout}")
Log.debug("prepare_exit: #{timeout}")
state = close_pipes(state, caller)

case maybe_shutdown(state) do
Expand Down Expand Up @@ -666,7 +665,7 @@ defmodule ExCmd.Process do
{:exit_sequence, current_stage, timeout, kill_timeout},
%{status: status} = state
) do
Logger.debug("exit_sequence, #{current_stage} #{timeout} #{kill_timeout}, #{inspect(state)}")
Log.debug("exit_sequence, #{current_stage} #{timeout} #{kill_timeout}, #{inspect(state)}")

cond do
status != :running ->
Expand Down Expand Up @@ -699,7 +698,7 @@ defmodule ExCmd.Process do
end

def handle_info({port, {:exit_status, odu_exit_status}}, %{port: port} = state) do
Logger.debug("port exit with status #{odu_exit_status} state: #{inspect(state)}")
Log.debug("port exit with status #{odu_exit_status} state: #{inspect(state)}")

state =
cond do
Expand All @@ -722,7 +721,7 @@ defmodule ExCmd.Process do

# we are only interested in Port exit signals
def handle_info({:EXIT, port, reason}, %State{port: port} = state) when reason != :normal do
Logger.debug("port exit with error state: #{inspect(state)}")
Log.debug("port exit with error state: #{inspect(state)}")

state =
state
Expand All @@ -733,7 +732,7 @@ defmodule ExCmd.Process do
end

def handle_info({:EXIT, port, :normal}, %State{port: port} = state) do
Logger.debug("port exit normally state: #{inspect(state)}")
Log.debug("port exit normally state: #{inspect(state)}")
maybe_shutdown(state)
end

Expand All @@ -744,27 +743,27 @@ defmodule ExCmd.Process do
{:DOWN, owner_ref, :process, _pid, reason},
%State{monitor_ref: owner_ref} = state
) do
Logger.debug("process owner exit: state: #{inspect(state)}")
Log.debug("process owner exit: state: #{inspect(state)}")
{:stop, reason, state}
end

def handle_info({:DOWN, _ref, :process, pid, _reason}, state) do
Logger.debug("pipe owner exit: state: #{inspect(state)}")
Log.debug("pipe owner exit: state: #{inspect(state)}")
state = close_pipes(state, pid)
maybe_shutdown(state)
end

@spec maybe_shutdown(State.t()) :: {:stop, :normal, State.t()} | {:noreply, State.t()}
defp maybe_shutdown(state) do
Logger.debug("maybe_shutdown: state: #{inspect(state)}")
Log.debug("maybe_shutdown: state: #{inspect(state)}")

open_pipes_count =
state.pipes
|> Map.values()
|> Enum.count(&Pipe.open?/1)

if open_pipes_count == 0 && !(state.status in [:init, :running]) do
Logger.debug("shutting down state: #{inspect(state)}")
Log.debug("shutting down state: #{inspect(state)}")
{:stop, :normal, state}
else
{:noreply, state}
Expand Down
9 changes: 4 additions & 5 deletions lib/ex_cmd/process/proto.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
defmodule ExCmd.Process.Proto do
@moduledoc false

alias ExCmd.Log
alias Mix.Tasks.Compile.Odu

require Logger

@doc false
defmacro send_input, do: 1

Expand Down Expand Up @@ -102,7 +101,7 @@ defmodule ExCmd.Process.Proto do
end

def close(port, stream) when is_port(port) do
Logger.debug("Closing stream: #{stream}")
Log.debug("Closing stream: #{stream}")
:ok
end

Expand All @@ -117,11 +116,11 @@ defmodule ExCmd.Process.Proto do
os_pid =
receive do
{^port, {:data, <<os_pid()::unsigned-integer-8, os_pid::big-unsigned-integer-32>>}} ->
Logger.debug("Command started. os pid: #{os_pid}")
Log.debug("Command started. os pid: #{os_pid}")
os_pid

{^port, {:data, <<start_error()::unsigned-integer-8, reason::binary>>}} ->
Logger.error("Failed to start odu. reason: #{reason}")
Log.error("Failed to start odu. reason: #{reason}")
raise ArgumentError, message: "Failed to start odu"
after
5_000 ->
Expand Down
1 change: 0 additions & 1 deletion lib/ex_cmd/process/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ defmodule ExCmd.Process.State do
@spec put_operation(State.t(), Operations.operation()) :: {:ok, t} | {:error, term}
def put_operation(%State{operations: ops} = state, operation) do
with {:ok, ops} <- Operations.put(ops, operation) do
# dbg(ops)
{:ok, %State{state | operations: ops}}
end
end
Expand Down
3 changes: 2 additions & 1 deletion test/ex_cmd_exit_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ defmodule ExCmdExitTest do
# currently running `elixir` command is not working in Windows
@tag os: :unix
test "if it kills external command on abnormal vm exit" do
ex_cmd_expr = ~S{ExCmd.stream!(["cat"]) |> Stream.run()}
ex_cmd_expr =
~S{:ok = Application.put_env(:ex_cmd, :enable_debug_logs, true); ExCmd.stream!(["cat"]) |> Stream.run()}

port =
Port.open(
Expand Down
Loading