diff --git a/lib/rack/server.rb b/lib/rack/server.rb index c8d32021a..5b0be39e7 100644 --- a/lib/rack/server.rb +++ b/lib/rack/server.rb @@ -324,11 +324,30 @@ def write_pid end def check_pid! - return unless ::File.exist?(options[:pid]) - pid = ::File.read(options[:pid]) + case pidfile_process_status + when :running + STDERR.puts "The process is still alive. aborting." + exit(1) + when :not_owned + STDERR.puts "The process is still alive. And owned by another user aborting." + exit(1) + when :dead + STDERR.puts "The process is no longer running. Removing the pid file." + ::File.delete(options[:pid]) + end + end + + def pidfile_process_status + return :exited unless ::File.exist?(options[:pid]) + + pid = ::File.read(options[:pid]).to_i STDERR.puts "There is already a pid file wrote a by process with pid #{pid}" - STDERR.puts "If this process is no longer running, you have to remove the pidfile #{options[:pid]}" - exit(1) + Process.kill(0, pid) + :running + rescue Errno::ESRCH + :dead + rescue Errno::EPERM + :not_owned end end diff --git a/test/spec_server.rb b/test/spec_server.rb index a1a51d9fa..bd61d622c 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -71,4 +71,30 @@ def app open(pidfile) { |f| f.read.should.eql $$.to_s } end + should "check pid file presence and running process" do + pidfile = Tempfile.open('pidfile') { |f| f.write($$); break f }.path + server = Rack::Server.new(:pid => pidfile) + server.send(:pidfile_process_status).should.eql :running + end + + should "check pid file presence and dead process" do + dead_pid = `echo $$`.to_i + pidfile = Tempfile.open('pidfile') { |f| f.write(dead_pid); break f }.path + server = Rack::Server.new(:pid => pidfile) + server.send(:pidfile_process_status).should.eql :dead + end + + should "check pid file presence and exited process" do + pidfile = Tempfile.open('pidfile') { |f| break f }.path + ::File.delete(pidfile) + server = Rack::Server.new(:pid => pidfile) + server.send(:pidfile_process_status).should.eql :exited + end + + should "check pid file presence and not owned process" do + pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path + server = Rack::Server.new(:pid => pidfile) + server.send(:pidfile_process_status).should.eql :not_owned + end + end