View Source Exile.Process (exile v0.1.0)

GenServer which wraps spawned external command.

Exile.stream!/1 should be preferred over using this. Use this only if you need more control over the life-cycle of IO streams and OS process.

comparison-with-port

Comparison with Port

  • it is demand driven. User explicitly has to read the command output, and the progress of the external command is controlled using OS pipes. Exile never load more output than we can consume, so we should never experience memory issues
  • it can close stdin while consuming output
  • tries to handle zombie process by attempting to cleanup external process. Note that there is no middleware involved with exile so it is still possbile to endup with zombie process.
  • selectively consume stdout and stderr streams

Internally Exile uses non-blocking asynchronous system calls to interact with the external process. It does not use port's message based communication, instead uses raw stdio and NIF. Uses asynchronous system calls for IO. Most of the system calls are non-blocking, so it should not block the beam schedulers. Make use of dirty-schedulers for IO

Link to this section Summary

Functions

Waits for the program to terminate.

Returns a specification to start this module under a supervisor.

Closes external program's input stream

Callback implementation for GenServer.init/1.

Sends signal to external program

Returns OS pid of the command

Returns bytes from executed command's stdout stream with maximum size max_size.

Returns bytes from either stdout or stderr stream with maximum size max_size whichever is availble.

Returns bytes from executed command's stderr stream with maximum size max_size.

Starts Exile.ProcessServer

Stops the exile process, external program will be terminated in the background

Writes iodata data to program's input streams

Link to this section Types

@type process() :: pid()

Link to this section Functions

Link to this function

await_exit(process, timeout \\ :infinity)

View Source
@spec await_exit(process(), [{:timeout, timeout()}]) :: {:ok, integer()} | :timeout

Waits for the program to terminate.

If the program terminates before timeout, it returns {:ok, exit_status} else returns :timeout

Returns a specification to start this module under a supervisor.

See Supervisor.

@spec close_stdin(process()) :: :ok | {:error, any()}

Closes external program's input stream

Link to this function

handle_continue(atom, state)

View Source

Callback implementation for GenServer.handle_continue/2.

Callback implementation for GenServer.init/1.

@spec kill(process(), :sigkill | :sigterm) :: :ok

Sends signal to external program

@spec os_pid(process()) :: pos_integer()

Returns OS pid of the command

Link to this function

read(process, max_size \\ 65535)

View Source
@spec read(process(), pos_integer()) :: {:ok, iodata()} | :eof | {:error, any()}

Returns bytes from executed command's stdout stream with maximum size max_size.

Blocks if no bytes are written to stdout stream yet. And returns as soon as bytes are availble

Link to this function

read_any(process, size \\ 65535)

View Source
@spec read_any(process(), pos_integer()) ::
  {:ok, {:stdout, iodata()}}
  | {:ok, {:stderr, iodata()}}
  | :eof
  | {:error, any()}

Returns bytes from either stdout or stderr stream with maximum size max_size whichever is availble.

Blocks if no bytes are written to stdout/stderr stream yet. And returns as soon as bytes are availble

Link to this function

read_stderr(process, size \\ 65535)

View Source
@spec read_stderr(process(), pos_integer()) ::
  {:ok, iodata()} | :eof | {:error, any()}

Returns bytes from executed command's stderr stream with maximum size max_size.

Blocks if no bytes are written to stdout stream yet. And returns as soon as bytes are availble

Link to this function

start_link(cmd_with_args, opts \\ [])

View Source
@spec start_link([String.t(), ...],
  cd: String.t(),
  env: [{String.t(), String.t()}],
  use_stderr: boolean()
) :: {:ok, process()} | {:error, any()}

Starts Exile.ProcessServer

Starts external program using cmd_with_args with options opts

cmd_with_args must be a list containing command with arguments. example: ["cat", "file.txt"].

options

Options

  • cd - the directory to run the command in
  • env - a list of tuples containing environment key-value. These can be accessed in the external program
  • use_stderr - when set to true, exile connects stderr stream for the consumption. Defaults to false. Note that when set to true stderr must be consumed to avoid external program from blocking
@spec stop(process()) :: :ok

Stops the exile process, external program will be terminated in the background

@spec write(process(), binary()) :: :ok | {:error, any()}

Writes iodata data to program's input streams

This blocks when the pipe is full