Skip to content

Commit

Permalink
Add --force (-f) option to force stopping of a daemonized server, [#72
Browse files Browse the repository at this point in the history
…state:resolved]
  • Loading branch information
macournoyer committed Jul 14, 2008
1 parent fef2e74 commit 729b76a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
@@ -1,4 +1,5 @@
== 1.0.0 The Big release
* Add --force (-f) option to force stopping of a daemonized server, fixes [#72 state:resolved]
* Update halycon adapter loader [mtodd]

== 0.8.2 Double Margarita release
Expand Down
2 changes: 1 addition & 1 deletion lib/thin/controllers/controller.rb
Expand Up @@ -83,7 +83,7 @@ def stop
raise OptionRequired, :pid unless @options[:pid]

tail_log(@options[:log]) do
if Server.kill(@options[:pid], @options[:timeout] || 60)
if Server.kill(@options[:pid], @options[:force] ? 0 : (@options[:timeout] || 60))
wait_for_file :deletion, @options[:pid]
end
end
Expand Down
37 changes: 19 additions & 18 deletions lib/thin/daemonizing.rb
Expand Up @@ -89,22 +89,16 @@ def restart
end

module ClassMethods
# Send a QUIT signal the process which PID is stored in +pid_file+.
# Send a QUIT or INT (if timeout is +0+) signal the process which
# PID is stored in +pid_file+.
# If the process is still running after +timeout+, KILL signal is
# sent.
def kill(pid_file, timeout=60)
if pid = send_signal('QUIT', pid_file)
Timeout.timeout(timeout) do
sleep 0.1 while Process.running?(pid)
end
if timeout == 0
send_signal('INT', pid_file, timeout)
else
send_signal('QUIT', pid_file, timeout)
end
rescue Timeout::Error
print "Timeout! "
send_signal('KILL', pid_file)
rescue Interrupt
send_signal('KILL', pid_file)
ensure
File.delete(pid_file) if File.exist?(pid_file)
end

# Restart the server by sending HUP signal.
Expand All @@ -113,21 +107,28 @@ def restart(pid_file)
end

# Send a +signal+ to the process which PID is stored in +pid_file+.
def send_signal(signal, pid_file)
if File.exist?(pid_file) && pid = open(pid_file).read
def send_signal(signal, pid_file, timeout=60)
if File.file?(pid_file) && pid = open(pid_file).read
pid = pid.to_i
print "Sending #{signal} signal to process #{pid} ... "
Process.kill(signal, pid)
Timeout.timeout(timeout) do
sleep 0.1 while Process.running?(pid)
end
puts
pid
else
puts "Can't stop process, no PID found in #{pid_file}"
nil
end
rescue Timeout::Error
puts "Timeout! "
Process.kill("KILL", pid)
rescue Interrupt
Process.kill("KILL", pid)
rescue Errno::ESRCH # No such process
puts "process not found!"
nil
end
ensure
File.delete(pid_file) if File.exist?(pid_file)
end
end

protected
Expand Down
1 change: 1 addition & 0 deletions lib/thin/runner.rb
Expand Up @@ -102,6 +102,7 @@ def parser
opts.on("-b", "--backend CLASS", "Backend to use, full classname") { |name| @options[:backend] = name }
opts.on("-t", "--timeout SEC", "Request or command timeout in sec " +
"(default: #{@options[:timeout]})") { |sec| @options[:timeout] = sec.to_i }
opts.on("-f", "--force", "Force the execution of the command") { @options[:force] = true }
opts.on( "--max-conns NUM", "Maximum number of connections " +
"(default: #{@options[:max_conns]})",
"Might require sudo to set higher then 1024") { |num| @options[:max_conns] = num.to_i } unless Thin.win?
Expand Down
17 changes: 17 additions & 0 deletions spec/daemonizing_spec.rb
Expand Up @@ -94,6 +94,23 @@ def name
File.exist?(@server.pid_file).should be_false
end

it 'should force kill process in pid file' do
@pid = fork do
@server.daemonize
loop { sleep 3 }
end

server_should_start_in_less_then 3

@pid = @server.pid

silence_stream STDOUT do
TestServer.kill(@server.pid_file, 0)
end

File.exist?(@server.pid_file).should be_false
end

it 'should send kill signal if timeout' do
@pid = fork do
@server.should_receive(:stop) # pretend we cannot handle the INT signal
Expand Down

0 comments on commit 729b76a

Please sign in to comment.