Module: Phantom

Defined in:
lib/phantom.rb,
lib/phantom/base.rb,
lib/phantom/phutex.rb,
lib/phantom/status.rb,
lib/phantom/version.rb,
lib/phantom/fork_error.rb,
lib/phantom/class_methods.rb

Defined Under Namespace

Modules: Status Classes: Base, ForkError, Phutex

Constant Summary collapse

VERSION =
'0.2.1'

Class Method Summary collapse

Class Method Details

.run(name: 'phantom', pid_file: nil, on_ok: nil, on_error: nil, &block) ⇒ Object

Raises:



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/phantom/class_methods.rb', line 4

def run(name: 'phantom', pid_file: nil, on_ok: nil, on_error: nil, &block)
  return Phantom::Base.new(nil) unless block_given?

  raise ForkError.new('Running process exists.', pid_file) if pid_file and File.exist?(pid_file)

  i, o = IO.pipe
  #f = File.new(pid_file, 'w') if pid_file

  pid = fork do
    $0 = name   # Change the subprocess name
    if pid_file
      File.open(pid_file, 'w') {|f| f.write Process.pid}
    end

    at_exit do
      o.flush
      o.close
      if pid_file and File.exists? pid_file
        File.delete pid_file if Process.pid == File.read(pid_file).to_i
      end
    end
    
    i.close
    begin
      block.call if block_given?
      Marshal.dump(Status::OK, o)
    rescue Exception => e
      status = e.is_a?(SignalException) ? Status::OK : e
      Marshal.dump(status, o)
    end
  end

  Process.detach(pid)
  #f.write(pid.to_s) if pid_file
  #f.close if pid_file
  o.close

  Thread.abort_on_exception = true
  Thread.new do
    begin
      status = Marshal.load(i)
      if status == Status::OK then
        on_ok.call if on_ok
      else
        on_error.call(status) if on_error
      end
    rescue Errno::EPIPE, EOFError => e
      on_error.call(e) if on_error
    ensure
      i.close
    end
  end

  return Phantom::Base.new(pid, name)
end