Class: Hoosegow::Protocol::Inmate

Inherits:
Object
  • Object
show all
Defined in:
lib/hoosegow/protocol.rb

Overview

bin/hoosegow client (where the inmate code runs)

Translates stdin into a method call on on inmate. Encodes yields and the return value onto a stream.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Inmate

Options:

  • :stdout - real stdout, where we can write things that our parent process will see

  • :intercepted - where this process or child processes write STDOUT to

  • (optional) :inmate - the hoosegow instance to use as the inmate.

  • (optional) :stdin - where to read the encoded method call data.



78
79
80
81
82
83
84
# File 'lib/hoosegow/protocol.rb', line 78

def initialize(options)
  @inmate       = options.fetch(:inmate) { Hoosegow.new(:no_proxy => true) }
  @stdin        = options.fetch(:stdin, $stdin)
  @stdout       = options.fetch(:stdout)
  @intercepted  = options.fetch(:intercepted)
  @stdout_mutex = Mutex.new
end

Class Method Details

.run(options) ⇒ Object



66
67
68
69
70
71
# File 'lib/hoosegow/protocol.rb', line 66

def self.run(options)
  o = new(options)
  o.intercepting do
    o.run
  end
end

Instance Method Details

#interceptingObject



97
98
99
100
101
102
# File 'lib/hoosegow/protocol.rb', line 97

def intercepting
  start_intercepting
  yield
ensure
  stop_intercepting
end

#runObject



86
87
88
89
90
91
92
93
94
95
# File 'lib/hoosegow/protocol.rb', line 86

def run
  name, args = MessagePack::Unpacker.new(@stdin).read
  result = @inmate.send(name, *args) do |*yielded|
    report(:yield, yielded)
    nil # Don't return anything from the inmate's `yield`.
  end
  report(:return, result)
rescue => e
  report(:raise, {:class => e.class.name, :message => e.message, :backtrace => e.backtrace})
end

#start_interceptingObject



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/hoosegow/protocol.rb', line 104

def start_intercepting
  @intercepting = true
  @intercept_thread = Thread.new do
    begin
      loop do
        if IO.select([@intercepted], nil, nil, 0.1)
          report(:stdout, @intercepted.read_nonblock(100000))
        elsif ! @intercepting
          break
        end
      end
    rescue EOFError
      # stdout is closed, so we can stop checking it.
    end
  end
end

#stop_interceptingObject



121
122
123
124
# File 'lib/hoosegow/protocol.rb', line 121

def stop_intercepting
  @intercepting = false
  @intercept_thread.join
end