# File lib/chef/shell_out.rb, line 156
    def run_command
      Chef::Log.debug("sh(#{@command})")
      @child_pid = fork_subprocess
      
      configure_parent_process_file_descriptors
      propagate_pre_exec_failure
        
      @result = nil
      @execution_time = 0
     
      # Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
      # when calling IO.select and IO#read. Some OS Vendors are not interested
      # in updating their ruby packages (Apple, *cough*) and we *have to*
      # make it work. So I give you this epic hack:
      GC.disable
      until @status
        ready = IO.select(open_pipes, nil, nil, READ_WAIT_TIME)
        unless ready
          @execution_time += READ_WAIT_TIME
          if @execution_time >= timeout && !@result
            raise Chef::Exceptions::CommandTimeout, "command timed out:\n#{format_for_exception}"
          end
        end
        
        if ready && ready.first.include?(child_stdout)
          read_stdout_to_buffer
        end
        if ready && ready.first.include?(child_stderr)
          read_stderr_to_buffer
        end
        
        unless @status
          # make one more pass to get the last of the output after the
          # child process dies
          if results = Process.waitpid2(@child_pid, Process::WNOHANG)
            @status = results.last
            redo
          end
        end
      end
      self
    rescue Exception
      # do our best to kill zombies
      Process.waitpid2(@child_pid, Process::WNOHANG) rescue nil
      raise
    ensure
      # 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