module Mixlib::ShellOut::Unix

def run_command

exit code if the command is killed by SIGKILL, also).
contain the correct exit code of the process (of course there is no
by bin/sh, and bin/sh is not bash), the exit status object may not
happens if the command is passed as a single string to be interpreted
the child process spawned multiple child processes (which commonly
that any grandchild processes are terminated. If the invocation of
will send a TERM and then KILL to the entire process group to ensure
within +timeout+ seconds (default: 600s). When this happens, ShellOut
* Chef::Exceptions::CommandTimeout when the command does not complete
in the current $PATH)
* Errno::ENOENT when the command is not available on the system (or not
* Errno::EACCES when you are not privileged to execute the command
=== Raises
populated with results of the command.
returns +self+; +stdout+, +stderr+, +status+, and +exitstatus+ will be
=== Returns
to +stdout+ and +stderr+, and saving its exit status object to +status+
Run the command, writing the command's standard out and standard error
def run_command
  @child_pid = fork_subprocess
  @reaped = false
  configure_parent_process_file_descriptors
  # Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC

  # when calling IO.select and IO#read. Disabling GC works around the

  # segfault, but obviously it's a bad workaround. We no longer support

  # 1.8.6 so we only need this hack for 1.8.7.

  GC.disable if RUBY_VERSION == ONE_DOT_EIGHT_DOT_SEVEN
  # CHEF-3390: Marshall.load on Ruby < 1.8.7p369 also has a GC bug related

  # to Marshall.load, so try disabling GC first.

  propagate_pre_exec_failure
  @status = nil
  @result = nil
  @execution_time = 0
  write_to_child_stdin
  until @status
    ready_buffers = attempt_buffer_read
    unless ready_buffers
      @execution_time += READ_WAIT_TIME
      if @execution_time >= timeout && !@result
        # kill the bad proccess

        reap_errant_child
        # read anything it wrote when we killed it

        attempt_buffer_read
        # raise

        raise CommandTimeout, "Command timed out after #{@execution_time.to_i}s:\n#{format_for_exception}"
      end
    end
    attempt_reap
  end
  self
rescue Errno::ENOENT
  # When ENOENT happens, we can be reasonably sure that the child process

  # is going to exit quickly, so we use the blocking variant of waitpid2

  reap
  raise
ensure
  reap_errant_child if should_reap?
  # make one more pass to get the last of the output after the

  # child process dies

  attempt_buffer_read
  # no matter what happens, turn the GC back on, and hope whatever busted

  # version of ruby we're on doesn't allocate some objects during the next

  # GC run.

  GC.enable
  close_all_pipes
end