class ProcessExecuter::Commands::Run


@api private
with ‘Process.spawn`.
destination. This means that you can redirect to a StringIO which is not possible
This allows any class that implements `#write` to be used as an output redirection
This class wraps any stdout or stderr redirection destinations in a {MonitoredPipe}.
plus the additional options `timeout_after`, `raise_errors` and `logger`.
options](docs.ruby-lang.org/en/3.4/Process.html#module-Process-label-Execution+Options)
It accepts all [Process.spawn execution
{ProcessExecuter.run}.
Extends {ProcessExecuter::Commands::SpawnWithTimeout} to provide the core functionality for
Run a command and return the {ProcessExecuter::Result}

def call

Returns:
  • (ProcessExecuter::Result) - The result of the completed subprocess

Raises:
  • (ProcessExecuter::ProcessIOError) - If there was an exception while
  • (ProcessExecuter::TimeoutError) - If the command timed out
  • (ProcessExecuter::SignaledError) - If the command ran and terminated due to
  • (ProcessExecuter::FailedError) - If the command ran and failed
  • (ProcessExecuter::SpawnError) - `Process.spawn` raised an error before the
def call
  opened_pipes = wrap_stdout_stderr
  super.tap do
    log_result
    raise_errors if options.raise_errors
  end
ensure
  opened_pipes.each_value(&:close)
  opened_pipes.each { |option_key, pipe| raise_pipe_error(option_key, pipe) }
end

def log_result

Returns:
  • (void) -
def log_result
  options.logger.info { "PID #{pid}: #{command} exited with status #{result}" }
end

def raise_errors

Raises:
  • (ProcessExecuter::TimeoutError) - If the command timed out
  • (ProcessExecuter::SignaledError) - If the command ran and terminated due to an unhandled signal
  • (ProcessExecuter::FailedError) - If the command ran and failed

Returns:
  • (void) -
def raise_errors
  raise TimeoutError, result if result.timed_out?
  raise SignaledError, result if result.signaled?
  raise FailedError, result unless result.success?
end

def raise_pipe_error(option_key, pipe)

Returns:
  • (void) -

Raises:
  • (ProcessExecuter::ProcessIOError) - If there was an exception while collecting subprocess output

Parameters:
  • pipe (ProcessExecuter::MonitoredPipe) -- The pipe that raised the exception
  • option_key (Object) -- The redirection option key
def raise_pipe_error(option_key, pipe)
  return unless pipe.exception
  error = ProcessExecuter::ProcessIOError.new("Pipe Exception for #{command}: #{option_key.inspect}")
  raise(error, cause: pipe.exception)
end

def should_wrap?(key, value)

Returns:
  • (Boolean) - Whether the option should be wrapped

Parameters:
  • value (Object) -- The option value
  • key (Object) -- The option key
def should_wrap?(key, value)
  (options.stdout_redirection?(key) || options.stderr_redirection?(key)) &&
    ProcessExecuter::Destinations.compatible_with_monitored_pipe?(value)
end

def wrap_stdout_stderr

Returns:
  • (Hash) - The opened pipes (the Object is the option key)
def wrap_stdout_stderr
  options.each_with_object({}) do |key_value, opened_pipes|
    key, value = key_value
    next unless should_wrap?(key, value)
    wrapped_destination = ProcessExecuter::MonitoredPipe.new(value)
    opened_pipes[key] = wrapped_destination
    options.merge!({ key => wrapped_destination })
  end
end