light-daemon 0.9.0 → 0.9.5

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 (2) hide show
  1. data/lib/light_daemon.rb +103 -50
  2. metadata +5 -5
@@ -1,49 +1,98 @@
1
1
  module LightDaemon
2
2
  class Daemon
3
- def initialize(obj, options={})
4
- @obj = obj
5
- @options = options
6
- log("before daemonize")
3
+ DEFAULT_PID_FILE = "/tmp/light_daemon.pid"
4
+
5
+ class << self
6
+ def start(obj, options={})
7
+ @options = self.make_options(options)
8
+ @pid_file = @options[:pid_file]
9
+ if self.get_pid
10
+ raise "The pid file \"#{@pid_file}\" existed already. You need to stop the daemon first."
11
+ end
12
+ self.new(obj, @options).start
13
+ end
14
+
15
+ def stop(pid_file=DEFAULT_PID_FILE)
16
+ @pid_file = pid_file
17
+ if(pid = self.get_pid)
18
+ begin
19
+ Process.kill("TERM", pid)
20
+ rescue Errno::ESRCH
21
+ # no such process. do nothing
22
+ end
23
+ self.clear_pid
24
+ end
25
+ end
26
+
27
+ def get_pid
28
+ return nil unless File.exist?(@pid_file)
29
+ begin
30
+ File.open(@pid_file) {|f| f.read}.to_i
31
+ rescue
32
+ nil
33
+ end
34
+ end
35
+
36
+ def set_pid(pid)
37
+ File.open(@pid_file, 'w') {|f| f.write(pid.to_s)}
38
+ end
39
+
40
+ def clear_pid
41
+ File.unlink(@pid_file)
42
+ end
43
+
44
+ def make_options(options)
45
+ options[:children] ||= 1
46
+ options[:monitor_cycle] ||= 10 # seconds
47
+ options[:pid_file] ||= DEFAULT_PID_FILE
48
+ options
49
+ end
50
+
51
+ # for debugging
52
+ # def log(msg)
53
+ # File.open("/tmp/yi.txt", "a") do |f|
54
+ # f.puts msg
55
+ # end
56
+ # end
57
+ end
58
+
59
+ def initialize(obj, options)
7
60
  daemonize
8
- log("after daemonize")
61
+ self.class.set_pid(Process.pid)
62
+
63
+ @options = options
64
+ @obj = obj
9
65
  @processes = []
66
+ @is_child = false
10
67
  signal_handling
11
68
  end
12
69
 
13
- def self.start(obj, options={})
14
- self.new(obj, options).start
15
- end
16
-
17
70
  def signal_handling
18
- $_simple_daemon_running = true
71
+ $keep_running = true
19
72
  Signal.trap "TERM" do
20
- log("Daemon received TERM !!!!!!!!!!!!!!!!!")
21
- @processes.each do |pid|
22
- Process.kill("TERM", pid)
23
- end
24
-
25
- sleep(3)
26
- 3.times do
27
- @processes.size.times do
28
- pid = @processes.shift
29
- if process_alive?(pid)
30
- @processes << pid
31
- sleep(3)
32
- end
33
- end
34
- end
35
- @processes.each do |pid|
36
- Process.kill(9, pid)
73
+ unless @is_child
74
+ @processes.each do |pid|
75
+ Process.kill("TERM", pid)
76
+ end
77
+
78
+ sleep(3)
79
+ options[:children].times do
80
+ @processes.size.times do
81
+ pid = @processes.shift
82
+ if process_alive?(pid)
83
+ @processes << pid
84
+ sleep(3)
85
+ end
86
+ end
87
+ end
88
+ @processes.each do |pid|
89
+ Process.kill(9, pid)
90
+ end
37
91
  end
38
- $_simple_daemon_running = false
92
+ $keep_running = false
39
93
  end
40
94
  end
41
95
 
42
- def log(msg)
43
- File.open("/tmp/yi.txt", "a") do |f|
44
- f.puts msg
45
- end
46
- end
47
96
 
48
97
  def process_alive?(pid)
49
98
  return false unless pid
@@ -57,33 +106,45 @@ module LightDaemon
57
106
  end
58
107
  end
59
108
 
60
-
61
109
  def start
62
- 5.times do
110
+ @options[:children].times do
63
111
  if pid = fork
64
112
  @processes << pid
65
113
  Process.detach(pid)
66
114
  else
67
- return @obj.send(:call)
115
+ set_child
116
+ while($keep_running)
117
+ break unless @obj.send(:call)
118
+ end
119
+ return
68
120
  end
69
121
  end
70
122
 
71
- while($_simple_daemon_running)
72
- sleep(5)
123
+ while($keep_running)
124
+ sleep(@options[:monitor_cycle])
125
+
73
126
  @processes.each_with_index do |pid, index|
74
127
  unless process_alive?(pid)
75
128
  if pid = fork
76
129
  @processes[index] = pid
77
130
  Process.detach(pid)
131
+ sleep(2)
78
132
  else
79
- return @obj.send(:call)
133
+ set_child
134
+ while($keep_running)
135
+ break unless @obj.send(:call)
136
+ end
137
+ return
80
138
  end
139
+ else
81
140
  end
82
141
  sleep(1)
83
142
  end
84
143
  end
144
+ self.class.clear_pid(@options[:pid_file])
85
145
  end
86
146
 
147
+ # some code in this method is learned from gem daemons
87
148
  def daemonize
88
149
  fork && exit
89
150
  unless Process.setsid
@@ -93,22 +154,14 @@ module LightDaemon
93
154
  trap 'SIGHUP', 'IGNORE'
94
155
  exit if fork
95
156
 
96
- ObjectSpace.each_object(IO) do |io|
97
- unless [STDIN, STDOUT, STDERR].include?(io)
98
- begin
99
- unless io.closed?
100
- io.close
101
- end
102
- rescue ::Exception
103
- end
104
- end
105
- end
106
-
107
157
  begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
108
158
  begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
109
159
  begin; STDERR.reopen STDOUT; rescue ::Exception; end
110
160
  STDERR.sync = true
161
+ end
111
162
 
163
+ def set_child
164
+ @is_child = true
112
165
  end
113
166
  end
114
167
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light-daemon
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 0
10
- version: 0.9.0
9
+ - 5
10
+ version: 0.9.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Yi Zhang
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-08 00:00:00 -08:00
18
+ date: 2012-03-10 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
22
- description: A simple and light daemon
22
+ description: A very simple and light ruby daemon API
23
23
  email: yzhang.wa@gmail.com
24
24
  executables: []
25
25