lib/angry_shell.rb
# Use select to read the entire contents of the pipes into StringIOs.
# This is the main change to come from Chef vs the original open4.
Use select to read the entire contents of the pipes into StringIOs.
This is the main change to come from Chef vs the original open4.
Use select to read the entire contents of the pipes into StringIOs . This is the main change to come from Chef vs the original open4 .
def popen4_parent_exhaust_io(cid,args,ipc,&blk)
      output = StringIO.new
      error  = StringIO.new
      if args[:input]
        ipc.write.puts args[:input]
      end
      ipc.write.close
      stdout = ipc.read
      stderr = ipc.error
      stdout.sync = true
      stderr.sync = true
      stdout.fcntl(Fcntl::F_SETFL, stdout.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
      stderr.fcntl(Fcntl::F_SETFL, stderr.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
      stdout_finished = false
      stderr_finished = false
      results = nil
      while !stdout_finished && !stderr_finished
        begin
          channels_to_watch = []
          channels_to_watch << stdout if !stdout_finished
          channels_to_watch << stderr if !stderr_finished
          ready = IO.select(channels_to_watch, nil, nil, 1.0)
        rescue Errno::EAGAIN
          results = Process.waitpid2(cid, Process::WNOHANG)
          if results
            stdout_finished = true
            stderr_finished = true 
          end
        end
        if ready && ready.first.include?(stdout)
          line = results ? stdout.gets(nil) : stdout.gets
          if line
            output.write(line)
          else
            stdout_finished = true
          end
        end
        if ready && ready.first.include?(stderr)
          line = results ? stderr.gets(nil) : stderr.gets
          if line
            error.write(line)
          else
            stderr_finished = true
          end
        end
      end
      results = Process.waitpid2(cid) unless results
      output.rewind
      error.rewind
      ipc.read = output
      ipc.error = error
      blk[cid, ipc]
      ShellResult.new(results.last, args)
    end
def popen4_parent_exhaust_io ( cid , args , ipc , & blk ) output = StringIO . new error = StringIO . new if args [ :input ] ipc . write . puts args [ :input ] end ipc . write . close stdout = ipc . read stderr = ipc . error stdout . sync = true stderr . sync = true stdout . fcntl ( Fcntl :: F_SETFL , stdout . fcntl ( Fcntl :: F_GETFL ) | Fcntl :: O_NONBLOCK ) stderr . fcntl ( Fcntl :: F_SETFL , stderr . fcntl ( Fcntl :: F_GETFL ) | Fcntl :: O_NONBLOCK ) stdout_finished = false stderr_finished = false results = nil while ! stdout_finished && ! stderr_finished begin channels_to_watch = [ ] channels_to_watch << stdout if ! stdout_finished channels_to_watch << stderr if ! stderr_finished ready = IO . select ( channels_to_watch , nil , nil , 1.0 ) rescue Errno :: EAGAIN results = Process . waitpid2 ( cid , Process :: WNOHANG ) if results stdout_finished = true stderr_finished = true end end if ready && ready . first . include? ( stdout ) line = results ? stdout . gets ( nil ) : stdout . gets if line output . write ( line ) else stdout_finished = true end end if ready && ready . first . include? ( stderr ) line = results ? stderr . gets ( nil ) : stderr . gets if line error . write ( line ) else stderr_finished = true end end end results = Process . waitpid2 ( cid ) unless results output . rewind error . rewind ipc . read = output ipc . error = error blk [ cid , ipc ] ShellResult . new ( results . last , args ) end
Use select to read the entire contents of the pipes into StringIOs.
Use select to read the entire contents of the pipes into StringIOs .
cid
args
ipc
blk