Class: Spork::Forker

Inherits:
Object
  • Object
show all
Defined in:
lib/spork/forker.rb

Overview

A helper class that allows you to run a block inside of a fork, and then get the result from that block.

Example:

forker = Spork::Forker.new do
  sleep 3
  "success"
end

forker.result # => "success"

Defined Under Namespace

Classes: ForkDiedException

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Forker

Returns a new instance of Forker.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/spork/forker.rb', line 15

def initialize(&block)
  return unless block_given?
  @child_io, @server_io = UNIXSocket.socketpair
  @child_pid = Kernel.fork do
    begin
      @server_io.close
      Marshal.dump(yield, @child_io)
      # wait for the parent to acknowledge receipt of the result.
      master_response = Marshal.load(@child_io)
    rescue EOFError
      nil
    rescue Exception => e
      puts "Exception encountered: #{e.inspect}\nbacktrace:\n#{e.backtrace * %(\n)}"
    end
    
    # terminate, skipping any at_exit blocks.
    exit!(0)
  end
  @child_io.close
end

Instance Method Details

#abortObject

abort the current running fork



56
57
58
59
60
61
62
# File 'lib/spork/forker.rb', line 56

def abort
  if running?
    Process.kill(Signal.list['TERM'], @child_pid)
    @child_pid = nil
    true
  end
end

#resultObject

Wait for the fork to finish running, and then return its return value.

If the fork was aborted, then result returns nil.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/spork/forker.rb', line 39

def result
  return unless running?
  result_thread = Thread.new do
    begin
      @result = Marshal.load(@server_io)
      Marshal.dump('ACK', @server_io)
    rescue ForkDiedException, EOFError
      @result = nil
    end
  end
  Process.wait(@child_pid)
  result_thread.raise(ForkDiedException) if @result.nil?
  @child_pid = nil
  @result
end

#running?Boolean

Returns:

  • (Boolean)


64
65
66
67
68
69
70
# File 'lib/spork/forker.rb', line 64

def running?
  return false unless @child_pid
  Process.getpgid(@child_pid)
  true
rescue Errno::ESRCH
  false
end