fire_and_forget 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/Gemfile.lock +0 -8
  2. data/README.rdoc +75 -14
  3. data/bin/fire_forget +45 -22
  4. data/examples/long_task +27 -16
  5. data/fire_and_forget.gemspec +41 -4
  6. data/lib/fire_and_forget/client.rb +1 -1
  7. data/lib/fire_and_forget/command/fire.rb +23 -4
  8. data/lib/fire_and_forget/command/get_pid.rb +20 -0
  9. data/lib/fire_and_forget/command/set_pid.rb +0 -2
  10. data/lib/fire_and_forget/command/set_status.rb +1 -1
  11. data/lib/fire_and_forget/command.rb +11 -0
  12. data/lib/fire_and_forget/config.rb +3 -8
  13. data/lib/fire_and_forget/daemon.rb +14 -23
  14. data/lib/fire_and_forget/errors.rb +8 -0
  15. data/lib/fire_and_forget/launcher.rb +69 -6
  16. data/lib/fire_and_forget/server.rb +5 -1
  17. data/lib/fire_and_forget/task_description.rb +11 -0
  18. data/lib/fire_and_forget/utilities.rb +4 -4
  19. data/lib/fire_and_forget/version.rb +1 -1
  20. data/lib/fire_and_forget.rb +6 -2
  21. data/test/test_fire_and_forget.rb +59 -26
  22. data/vendor/daemons-1.1.0/LICENSE +29 -0
  23. data/vendor/daemons-1.1.0/README +224 -0
  24. data/vendor/daemons-1.1.0/Rakefile +88 -0
  25. data/vendor/daemons-1.1.0/Releases +152 -0
  26. data/vendor/daemons-1.1.0/TODO +2 -0
  27. data/vendor/daemons-1.1.0/lib/daemons/application.rb +468 -0
  28. data/vendor/daemons-1.1.0/lib/daemons/application_group.rb +194 -0
  29. data/vendor/daemons-1.1.0/lib/daemons/change_privilege.rb +19 -0
  30. data/vendor/daemons-1.1.0/lib/daemons/cmdline.rb +124 -0
  31. data/vendor/daemons-1.1.0/lib/daemons/controller.rb +140 -0
  32. data/vendor/daemons-1.1.0/lib/daemons/daemonize.rb +271 -0
  33. data/vendor/daemons-1.1.0/lib/daemons/etc_extension.rb +12 -0
  34. data/vendor/daemons-1.1.0/lib/daemons/exceptions.rb +28 -0
  35. data/vendor/daemons-1.1.0/lib/daemons/monitor.rb +138 -0
  36. data/vendor/daemons-1.1.0/lib/daemons/pid.rb +109 -0
  37. data/vendor/daemons-1.1.0/lib/daemons/pidfile.rb +116 -0
  38. data/vendor/daemons-1.1.0/lib/daemons/pidmem.rb +19 -0
  39. data/vendor/daemons-1.1.0/lib/daemons.rb +288 -0
  40. data/vendor/daemons-1.1.0/setup.rb +1360 -0
  41. data/vendor/json-1.5.0/COPYING +58 -0
  42. data/vendor/json-1.5.0/GPL +340 -0
  43. data/vendor/json-1.5.0/README +356 -0
  44. data/vendor/json-1.5.0/README-json-jruby.markdown +33 -0
  45. data/vendor/json-1.5.0/Rakefile +397 -0
  46. data/vendor/json-1.5.0/TODO +1 -0
  47. data/vendor/json-1.5.0/VERSION +1 -0
  48. data/vendor/json-1.5.0/lib/json/add/core.rb +147 -0
  49. data/vendor/json-1.5.0/lib/json/add/rails.rb +8 -0
  50. data/vendor/json-1.5.0/lib/json/common.rb +419 -0
  51. data/vendor/json-1.5.0/lib/json/editor.rb +1369 -0
  52. data/vendor/json-1.5.0/lib/json/pure/generator.rb +441 -0
  53. data/vendor/json-1.5.0/lib/json/pure/parser.rb +320 -0
  54. data/vendor/json-1.5.0/lib/json/pure.rb +15 -0
  55. data/vendor/json-1.5.0/lib/json/version.rb +8 -0
  56. data/vendor/json-1.5.0/lib/json.rb +10 -0
  57. metadata +41 -4
  58. data/lib/fire_and_forget/task.rb +0 -11
@@ -0,0 +1,271 @@
1
+ #--
2
+ ###############################################################################
3
+ # daemonize.rb is a slightly modified version of daemonize.rb was #
4
+ # from the Daemonize Library written by Travis Whitton #
5
+ # for details, read the notice below #
6
+ ###############################################################################
7
+ #++
8
+ #
9
+ #
10
+ # =Daemonize Library
11
+ #
12
+ # February. 4, 2005 Travis Whitton <whitton@atlantic.net>
13
+ #
14
+ # Daemonize allows you to easily modify any existing Ruby program to run
15
+ # as a daemon. See README.rdoc for more details.
16
+ #
17
+ # == How to install
18
+ # 1. su to root
19
+ # 2. ruby install.rb
20
+ # build the docs if you want to
21
+ # 3. rdoc --main README.rdoc daemonize.rb README.rdoc
22
+ #
23
+ # == Copying
24
+ # The Daemonize extension module is copywrited free software by Travis Whitton
25
+ # <whitton@atlantic.net>. You can redistribute it under the terms specified in
26
+ # the COPYING file of the Ruby distribution.
27
+ #
28
+ # == WARRANTY
29
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
30
+ # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31
+ # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
32
+ # PURPOSE.
33
+ #
34
+ #
35
+ # ----
36
+ #
37
+ # == Purpose
38
+ #
39
+ # Daemonize is a module derived from Perl's Proc::Daemon module. This module
40
+ # allows you to easily modify any existing Ruby program to run as a daemon.
41
+ # A daemon is a process that runs in the background with no controlling terminal.
42
+ # Generally servers (like FTP and HTTP servers) run as daemon processes.
43
+ # Note, do not make the mistake that a daemon == server. Converting a program
44
+ # to a daemon by hand is a relatively simple process; however, this module will
45
+ # save you the effort of repeatedly looking up the procedure, and it will also
46
+ # insure that your programs are daemonized in the safest and most corrects
47
+ # fashion possible.
48
+ #
49
+ # == Procedure
50
+ #
51
+ # The Daemonize module does the following:
52
+ #
53
+ # Forks a child and exits the parent process.
54
+ #
55
+ # Becomes a session leader (which detaches the program from
56
+ # the controlling terminal).
57
+ #
58
+ # Forks another child process and exits first child. This prevents
59
+ # the potential of acquiring a controlling terminal.
60
+ #
61
+ # Changes the current working directory to "/".
62
+ #
63
+ # Clears the file creation mask.
64
+ #
65
+ # Closes file descriptors.
66
+ #
67
+ # == Example usage
68
+ #
69
+ # Using the Daemonize module is extremely simple:
70
+ #
71
+ # require 'daemonize'
72
+ #
73
+ # class TestDaemon
74
+ # include Daemonize
75
+ #
76
+ # def initialize
77
+ # daemonize()
78
+ # loop do
79
+ # # do some work here
80
+ # end
81
+ # end
82
+ # end
83
+ #
84
+ # == Credits
85
+ #
86
+ # Daemonize was written by Travis Whitton and is based on Perl's
87
+ # Proc::Daemonize, which was written by Earl Hood. The above documentation
88
+ # is also partially borrowed from the Proc::Daemonize POD documentation.
89
+
90
+
91
+
92
+ module Daemonize
93
+ VERSION = "0.1.1m"
94
+
95
+ # Try to fork if at all possible retrying every 5 sec if the
96
+ # maximum process limit for the system has been reached
97
+ def safefork
98
+ tryagain = true
99
+
100
+ while tryagain
101
+ tryagain = false
102
+ begin
103
+ if pid = fork
104
+ return pid
105
+ end
106
+ rescue Errno::EWOULDBLOCK
107
+ sleep 5
108
+ tryagain = true
109
+ end
110
+ end
111
+ end
112
+ module_function :safefork
113
+
114
+
115
+ def simulate(logfile_name = nil)
116
+ # NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
117
+
118
+ Dir.chdir "/" # Release old working directory
119
+ File.umask 0000 # Insure sensible umask
120
+
121
+ # Make sure all file descriptors are closed
122
+ ObjectSpace.each_object(IO) do |io|
123
+ unless [STDIN, STDOUT, STDERR].include?(io)
124
+ begin
125
+ unless io.closed?
126
+ io.close
127
+ end
128
+ rescue ::Exception
129
+ end
130
+ end
131
+ end
132
+
133
+ # Free file descriptors and
134
+ # point them somewhere sensible
135
+ # STDOUT/STDERR should go to a logfile
136
+
137
+ begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
138
+ end
139
+ module_function :simulate
140
+
141
+
142
+ def call_as_daemon(block, logfile_name = nil, app_name = nil)
143
+ rd, wr = IO.pipe
144
+
145
+ if tmppid = safefork
146
+ # parent
147
+ wr.close
148
+ pid = rd.read.to_i
149
+ rd.close
150
+
151
+ Process.waitpid(tmppid)
152
+
153
+ return pid
154
+ else
155
+ # child
156
+
157
+ rd.close
158
+
159
+ # Detach from the controlling terminal
160
+ unless sess_id = Process.setsid
161
+ raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
162
+ end
163
+
164
+ # Prevent the possibility of acquiring a controlling terminal
165
+ #if oldmode.zero?
166
+ trap 'SIGHUP', 'IGNORE'
167
+ exit if pid = safefork
168
+ #end
169
+
170
+ wr.write Process.pid
171
+ wr.close
172
+
173
+ $0 = app_name if app_name
174
+
175
+ Dir.chdir "/" # Release old working directory
176
+ File.umask 0000 # Insure sensible umask
177
+
178
+ # Make sure all file descriptors are closed
179
+ ObjectSpace.each_object(IO) do |io|
180
+ unless [STDIN, STDOUT, STDERR].include?(io)
181
+ begin
182
+ unless io.closed?
183
+ io.close
184
+ end
185
+ rescue ::Exception
186
+ end
187
+ end
188
+ end
189
+
190
+ ios = Array.new(8192){|i| IO.for_fd(i) rescue nil}.compact
191
+ ios.each do |io|
192
+ next if io.fileno < 3
193
+ io.close
194
+ end
195
+
196
+
197
+ redirect_io(logfile_name)
198
+
199
+ block.call
200
+
201
+ exit
202
+ end
203
+ end
204
+ module_function :call_as_daemon
205
+
206
+
207
+ # This method causes the current running process to become a daemon
208
+ def daemonize(logfile_name = nil, app_name = nil)
209
+ srand # Split rand streams between spawning and daemonized process
210
+ safefork and exit # Fork and exit from the parent
211
+
212
+ # Detach from the controlling terminal
213
+ unless sess_id = Process.setsid
214
+ raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
215
+ end
216
+
217
+ # Prevent the possibility of acquiring a controlling terminal
218
+ #if oldmode.zero?
219
+ trap 'SIGHUP', 'IGNORE'
220
+ exit if pid = safefork
221
+ #end
222
+
223
+ $0 = app_name if app_name
224
+
225
+ Dir.chdir "/" # Release old working directory
226
+ File.umask 0000 # Insure sensible umask
227
+
228
+ # Make sure all file descriptors are closed
229
+ ObjectSpace.each_object(IO) do |io|
230
+ unless [STDIN, STDOUT, STDERR].include?(io)
231
+ begin
232
+ unless io.closed?
233
+ io.close
234
+ end
235
+ rescue ::Exception
236
+ end
237
+ end
238
+ end
239
+
240
+ redirect_io(logfile_name)
241
+
242
+ #return oldmode ? sess_id : 0 # Return value is mostly irrelevant
243
+ return sess_id
244
+ end
245
+ module_function :daemonize
246
+
247
+
248
+ # Free file descriptors and
249
+ # point them somewhere sensible
250
+ # STDOUT/STDERR should go to a logfile
251
+ def redirect_io(logfile_name)
252
+ begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
253
+
254
+ if logfile_name
255
+ begin
256
+ STDOUT.reopen logfile_name, "a"
257
+ File.chmod(0644, logfile_name)
258
+ STDOUT.sync = true
259
+ rescue ::Exception
260
+ begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
261
+ end
262
+ else
263
+ begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
264
+ end
265
+
266
+ begin; STDERR.reopen STDOUT; rescue ::Exception; end
267
+ STDERR.sync = true
268
+ end
269
+ module_function :redirect_io
270
+
271
+ end
@@ -0,0 +1,12 @@
1
+ require 'etc'
2
+
3
+ Etc.instance_eval do
4
+ def groupname(gid)
5
+ Etc.group {|e| return e.name if gid == e.gid }
6
+ nil
7
+ end
8
+ def username(uid)
9
+ Etc.passwd {|e| return e.name if uid == e.uid }
10
+ nil
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Daemons
3
+
4
+ class Exception < ::RuntimeError
5
+ end
6
+
7
+ class RuntimeException < Exception
8
+ end
9
+
10
+ class CmdException < Exception
11
+ end
12
+
13
+ class Error < Exception
14
+ end
15
+
16
+ class SystemError < Error
17
+
18
+ attr_reader :system_error
19
+
20
+ def initialize(msg, system_error)
21
+ super(msg)
22
+
23
+ @system_error = system_error
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,138 @@
1
+
2
+ module Daemons
3
+
4
+ require 'daemons/daemonize'
5
+
6
+ class Monitor
7
+
8
+ def self.find(dir, app_name)
9
+ pid = PidFile.find_files(dir, app_name, false)[0]
10
+
11
+ if pid
12
+ pid = PidFile.existing(pid)
13
+
14
+ unless PidFile.running?(pid.pid)
15
+ begin; pid.cleanup; rescue ::Exception; end
16
+ return
17
+ end
18
+
19
+ monitor = self.allocate
20
+
21
+ monitor.instance_variable_set(:@pid, pid)
22
+
23
+ return monitor
24
+ end
25
+
26
+ return nil
27
+ end
28
+
29
+
30
+ def initialize(an_app)
31
+ @app = an_app
32
+ @app_name = an_app.group.app_name + '_monitor'
33
+
34
+ if an_app.pidfile_dir
35
+ @pid = PidFile.new(an_app.pidfile_dir, @app_name, false)
36
+ else
37
+ @pid = PidMem.new
38
+ end
39
+ end
40
+
41
+ def watch(applications)
42
+ sleep(30)
43
+
44
+ loop do
45
+ applications.each {|a|
46
+ sleep(10)
47
+
48
+ unless a.running?
49
+ a.zap!
50
+
51
+ Process.detach(fork { a.start })
52
+
53
+ sleep(10)
54
+ end
55
+ }
56
+
57
+ sleep(30)
58
+ end
59
+ end
60
+ private :watch
61
+
62
+
63
+ def start_with_pidfile(applications)
64
+ fork do
65
+ Daemonize.daemonize(nil, @app_name)
66
+
67
+ begin
68
+ @pid.pid = Process.pid
69
+
70
+ # at_exit {
71
+ # begin; @pid.cleanup; rescue ::Exception; end
72
+ # }
73
+
74
+ # This part is needed to remove the pid-file if the application is killed by
75
+ # daemons or manually by the user.
76
+ # Note that the applications is not supposed to overwrite the signal handler for
77
+ # 'TERM'.
78
+ #
79
+ # trap('TERM') {
80
+ # begin; @pid.cleanup; rescue ::Exception; end
81
+ # exit
82
+ # }
83
+
84
+ watch(applications)
85
+ rescue ::Exception => e
86
+ begin
87
+ File.open(@app.logfile, 'a') {|f|
88
+ f.puts Time.now
89
+ f.puts e
90
+ f.puts e.backtrace.inspect
91
+ }
92
+ ensure
93
+ begin; @pid.cleanup; rescue ::Exception; end
94
+ exit!
95
+ end
96
+ end
97
+ end
98
+ end
99
+ private :start_with_pidfile
100
+
101
+ def start_without_pidfile(applications)
102
+ Thread.new { watch(applications) }
103
+ end
104
+ private :start_without_pidfile
105
+
106
+
107
+ def start(applications)
108
+ return if applications.empty?
109
+
110
+ if @pid.kind_of?(PidFile)
111
+ start_with_pidfile(applications)
112
+ else
113
+ start_without_pidfile(applications)
114
+ end
115
+ end
116
+
117
+
118
+ def stop
119
+ begin
120
+ pid = @pid.pid
121
+ Process.kill(Application::SIGNAL, pid)
122
+ Timeout::timeout(5) {
123
+ while Pid.running?(pid)
124
+ sleep(0.1)
125
+ end
126
+ }
127
+ rescue ::Exception => e
128
+ puts "#{e} #{pid}"
129
+ puts "deleting pid-file."
130
+ end
131
+
132
+ # We try to remove the pid-files by ourselves, in case the application
133
+ # didn't clean it up.
134
+ begin; @pid.cleanup; rescue ::Exception; end
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,109 @@
1
+ require 'open3'
2
+
3
+
4
+ module Daemons
5
+
6
+ class Pid
7
+
8
+ def Pid.running?(pid)
9
+ return false unless pid
10
+
11
+ # Check if process is in existence
12
+ # The simplest way to do this is to send signal '0'
13
+ # (which is a single system call) that doesn't actually
14
+ # send a signal
15
+ begin
16
+ Process.kill(0, pid)
17
+ return true
18
+ rescue Errno::ESRCH
19
+ return false
20
+ rescue ::Exception # for example on EPERM (process exists but does not belong to us)
21
+ return true
22
+ #rescue Errno::EPERM
23
+ # return false
24
+ end
25
+ end
26
+
27
+ # def Pid.running?(pid, additional = nil)
28
+ # match_pid = Regexp.new("^\\s*#{pid}\\s")
29
+ # got_match = false
30
+ #
31
+ # #ps_all = IO.popen('ps ax') # the correct syntax is without a dash (-) !
32
+ # ps_in, ps_out, ps_err = Open3.popen3('ps ax') # the correct syntax is without a dash (-) !
33
+ #
34
+ # return true unless ps_out.gets
35
+ #
36
+ # begin
37
+ # ps_out.each { |psline|
38
+ # next unless psline =~ match_pid
39
+ # got_match = true
40
+ # got_match = false if additional and psline !~ /#{additional}/
41
+ # break
42
+ # }
43
+ # ensure
44
+ # begin; begin; ps_in.close; rescue ::Exception; end; begin; ps_out.close; rescue ::Exception; end; ps_err.close; rescue ::Exception; end
45
+ # end
46
+ #
47
+ # # an alternative would be to use the code below, but I don't know whether this is portable
48
+ # # `ps axo pid=`.split.include? pid.to_s
49
+ #
50
+ # return got_match
51
+ # end
52
+
53
+
54
+
55
+ # Returns the directory that should be used to write the pid file to
56
+ # depending on the given mode.
57
+ #
58
+ # Some modes may require an additionaly hint, others may determine
59
+ # the directory automatically.
60
+ #
61
+ # If no valid directory is found, returns nil.
62
+ #
63
+ def Pid.dir(dir_mode, dir, script)
64
+ # nil script parameter is allowed as long as dir_mode is not :script
65
+ return nil if dir_mode == :script && script.nil?
66
+
67
+ case dir_mode
68
+ when :normal
69
+ return File.expand_path(dir)
70
+ when :script
71
+ return File.expand_path(File.join(File.dirname(script),dir))
72
+ when :system
73
+ return '/var/run'
74
+ else
75
+ raise Error.new("pid file mode '#{dir_mode}' not implemented")
76
+ end
77
+ end
78
+
79
+ # Initialization method
80
+ def initialize
81
+ end
82
+
83
+
84
+ # Get method
85
+ def pid
86
+ end
87
+
88
+ # Set method
89
+ def pid=(p)
90
+ end
91
+
92
+ # Check whether the process is running
93
+ def running?
94
+ return Pid.running?(pid())
95
+ end
96
+
97
+ # Cleanup method
98
+ def cleanup
99
+ end
100
+
101
+ # Exist? method
102
+ def exist?
103
+ true
104
+ end
105
+
106
+ end
107
+
108
+
109
+ end
@@ -0,0 +1,116 @@
1
+ require 'daemons/pid'
2
+
3
+
4
+ module Daemons
5
+
6
+ # === What is a Pid-File?
7
+ # A <i>Pid-File</i> is a file containing the <i>process identification number</i>
8
+ # (pid) that is stored in a well-defined location of the filesystem thus allowing other
9
+ # programs to find out the pid of a running script.
10
+ #
11
+ # Daemons needs the pid of the scripts that are currently running in the background
12
+ # to send them so called _signals_. Daemons uses the +TERM+ signal to tell the script
13
+ # to exit when you issue a +stop+ command.
14
+ #
15
+ # === How does a Pid-File look like?
16
+ #
17
+ # Pid-Files generated by Daemons have to following format:
18
+ # <scriptname>.rb<number>.pid
19
+ # (Note that <tt><number></tt> is omitted if only one instance of the script can
20
+ # run at any time)
21
+ #
22
+ # Each file just contains one line with the pid as string (for example <tt>6432</tt>).
23
+ #
24
+ # === Where are the Pid-Files stored?
25
+ #
26
+ # Daemons is configurable to store the Pid-Files relative to three different locations:
27
+ # 1. in a directory relative to the directory where the script (the one that is supposed to run
28
+ # as a daemon) resides (<tt>:script</tt> option for <tt>:dir_mode</tt>)
29
+ # 2. in a directory given by <tt>:dir</tt> (<tt>:normal</tt> option for <tt>:dir_mode</tt>)
30
+ # 3. in the preconfigured directory <tt>/var/run</tt> (<tt>:system</tt> option for <tt>:dir_mode</tt>)
31
+ #
32
+ class PidFile < Pid
33
+
34
+ attr_reader :dir, :progname, :multiple, :number
35
+
36
+ def PidFile.find_files(dir, progname, delete = false)
37
+ files = Dir[File.join(dir, "#{progname}*.pid")]
38
+
39
+ files.delete_if {|f| not (File.file?(f) and File.readable?(f))}
40
+ if delete
41
+ files.delete_if do |f|
42
+ pid = File.open(f) {|h| h.read}.to_i
43
+ rsl = ! Pid.running?(pid)
44
+ if rsl
45
+ puts "pid-file for killed process #{pid} found (#{f}), deleting."
46
+ begin; File.unlink(f); rescue ::Exception; end
47
+ end
48
+ rsl
49
+ end
50
+ end
51
+
52
+ return files
53
+ end
54
+
55
+ def PidFile.existing(path)
56
+ new_instance = PidFile.allocate
57
+
58
+ new_instance.instance_variable_set(:@path, path)
59
+
60
+ def new_instance.filename
61
+ return @path
62
+ end
63
+
64
+ return new_instance
65
+ end
66
+
67
+ def initialize(dir, progname, multiple = false)
68
+ @dir = File.expand_path(dir)
69
+ @progname = progname
70
+ @multiple = multiple
71
+ @number = nil
72
+ @number = 0 if multiple
73
+
74
+ if multiple
75
+ while File.exist?(filename) and @number < 1024
76
+ @number += 1
77
+ end
78
+
79
+ if @number == 1024
80
+ raise RuntimeException('cannot run more than 1024 instances of the application')
81
+ end
82
+ end
83
+ end
84
+
85
+ def filename
86
+ File.join(@dir, "#{@progname}#{ @number or '' }.pid")
87
+ end
88
+
89
+ def exist?
90
+ File.exist? filename
91
+ end
92
+
93
+ def pid=(p)
94
+ File.open(filename, 'w') {|f|
95
+ f.chmod(0644)
96
+ f.puts p #Process.pid
97
+ }
98
+ end
99
+
100
+ def cleanup
101
+ File.delete(filename) if pid == Process.pid
102
+ end
103
+
104
+ def pid
105
+ begin
106
+ File.open(filename) {|f|
107
+ return f.gets.to_i
108
+ }
109
+ rescue ::Exception
110
+ return nil
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,19 @@
1
+ require 'daemons/pid'
2
+
3
+
4
+ module Daemons
5
+
6
+ class PidMem < Pid
7
+ attr_accessor :pid
8
+
9
+ def PidMem.existing(numeric_pid)
10
+ new_instance = PidMem.allocate
11
+
12
+ new_instance.instance_variable_set(:@pid, numeric_pid)
13
+
14
+ return new_instance
15
+ end
16
+
17
+ end
18
+
19
+ end