Module: Forkoff

Extended by:
Forkoff
Included in:
Forkoff
Defined in:
lib/forkoff.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

STRATEGIES =
Hash.new do |h, key|
  strategy = key.to_s.strip.downcase.to_sym
  raise ArgumentError, "strategy=#{ strategy.class }(#{ strategy.inspect })" unless h.has_key?(strategy)
  h[key] = h[strategy]
end

Instance Method Summary collapse

Instance Method Details

#defaultObject



8
9
10
# File 'lib/forkoff.rb', line 8

def default
  @default ||= { 'processes' => 2 }
end

#fileObject



16
17
18
# File 'lib/forkoff.rb', line 16

def file 
  'file'
end

#file_result(arg, &block) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/forkoff.rb', line 103

def file_result arg, &block
  tmpfile do |fd|
    pid = fork

    unless pid
      result =
        begin
          block.call(arg)
        rescue Object => e
          e
        end
      fd.write( Marshal.dump( result ) )
      exit!
    end

    Process.waitpid pid
    fd.rewind
    data = fd.read
    result = Marshal.load( data )
    return result
  end
end

#hostnameObject



32
33
34
35
# File 'lib/forkoff.rb', line 32

def hostname
  require 'socket'
  @hostname ||= (Socket.gethostname rescue 'localhost.localdomain')
end

#pidObject



20
21
22
# File 'lib/forkoff.rb', line 20

def pid
  @pid ||= Process.pid
end

#pipeObject



12
13
14
# File 'lib/forkoff.rb', line 12

def pipe
  'pipe'
end

#pipe_result(arg, &block) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/forkoff.rb', line 75

def pipe_result arg, &block
  r, w = IO.pipe
  pid = fork

  unless pid
    r.close
    result =
      begin
        block.call(arg)
      rescue Object => e
        e
      end
    w.write( Marshal.dump( result ) )
    w.close
    exit!
  end

  w.close
  data = ''
  while(( buf = r.read(8192) ))
    data << buf
  end
  result = Marshal.load( data )
  r.close
  Process.waitpid pid
  return result
end

#ppidObject



24
25
26
# File 'lib/forkoff.rb', line 24

def ppid
  @ppid ||= Process.ppid
end

#tidObject



28
29
30
# File 'lib/forkoff.rb', line 28

def tid
  Thread.current.object_id.abs
end

#tmpdirObject



37
38
39
40
# File 'lib/forkoff.rb', line 37

def tmpdir
  require 'tmpdir'
  @tmpdir ||= Dir.tmpdir
end

#tmpdir=(tmpdir) ⇒ Object



42
43
44
# File 'lib/forkoff.rb', line 42

def tmpdir= tmpdir
  @tmpdir = tmpdir.to_s
end

#tmpfile(&block) ⇒ Object

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/forkoff.rb', line 46

def tmpfile &block
  basename = [hostname, pid, ppid, tid, rand].join('-') 
  tmp = File.join(tmpdir, basename)

  fd = nil
  flags = File::CREAT|File::EXCL|File::RDWR

  42.times do
    begin
      fd = open tmp, flags
      break
    rescue Object
      sleep rand
    end
  end
  raise Error, "could not create tmpfile" unless fd

  if block
    begin
      return block.call(fd)
    ensure
      fd.close unless fd.closed? rescue nil
      FileUtils.rm_rf tmp rescue nil
    end
  else
    return fd
  end
end

#versionObject



4
5
6
# File 'lib/forkoff.rb', line 4

def version
  '1.2.0'
end