如何在Ruby中解决管道死锁问题?

时间:2014-01-16 21:22:24

标签: ruby pipe deadlock

我试图在使用多核的仅使用Ruby的解决方案中模拟UNIX命令行管道。最终,从命令到命令管道的记录将是使用msgpack封送的Ruby对象。不幸的是,下面的代码在第一个dump命令后挂起。我怀疑管道死锁,但我无法解决它?

#!/usr/bin/env ruby

require 'parallel'
require 'msgpack'
require 'pp'

class Pipe
  def initialize
    @commands = []
  end

  def add(command, options = {})
    @commands << Command.new(command, options)

    self
  end

  def run
    @commands.each_cons(2) do |c_in, c_out|
      reader, writer = IO.pipe

      c_out.input = MessagePack::Unpacker.new(reader)
      c_in.output = MessagePack::Packer.new(writer)
    end

    Parallel.each(@commands, in_processes: @commands.size) { |command| command.run }

    self
  end

  class Command
    attr_accessor :input, :output

    def initialize(command, options)
      @command = command
      @options = options
      @input   = nil
      @output  = nil
    end

    def run
      send @command
    end

    def cat
      @input.each_with_index { |record, i| @output.write(record).flush } if @input

      File.open(@options[:input]) do |ios|
        ios.each { |record| @output.write(record).flush } if @output
      end
    end

    def dump
      @input.each do |record|
        puts record
        @output.write(record).flush if @output
      end
    end
  end
end

p = Pipe.new
p.add(:cat, input: "foo.tab").add(:dump).add(:cat, input: "table.txt").add(:dump)
p.run

0 个答案:

没有答案