Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Stop overwriting existing pidfiles.

A race condition can arise when two servers are started simultaneously. Both
instances may complete the check for an existing pidfile before either one
writes it.

Now the pidfile is opened with ::File::EXCL, which raises an error if the file
already exists. This error is handled by retrying the check and the write.
  • Loading branch information...
commit 85b50e2135db1c2773a3c1025b5813e523beb324 1 parent 42b11a7
Tim Moore TimMoore authored
Showing with 20 additions and 1 deletion.
  1. +4 −1 lib/rack/server.rb
  2. +16 −0 test/spec_server.rb
5 lib/rack/server.rb
View
@@ -329,8 +329,11 @@ def daemonize_app
end
def write_pid
- ::File.open(options[:pid], 'w'){ |f| f.write("#{Process.pid}") }
+ ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") }
at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
+ rescue Errno::EEXIST
+ check_pid!
+ retry
end
def check_pid!
16 test/spec_server.rb
View
@@ -110,6 +110,22 @@ def with_stderr
server.send(:pidfile_process_status).should.eql :not_owned
end
+ should "not write pid file when it is created after check" do
+ pidfile = Tempfile.open('pidfile') { |f| break f }.path
+ ::File.delete(pidfile)
+ server = Rack::Server.new(:pid => pidfile)
+ ::File.open(pidfile, 'w') { |f| f.write(1) }
+ with_stderr do |err|
+ should.raise(SystemExit) do
+ server.send(:write_pid)
+ end
+ err.rewind
+ output = err.read
+ output.should.match(/already running/)
+ output.should.include? pidfile
+ end
+ end
+
should "inform the user about existing pidfiles with running processes" do
pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path
server = Rack::Server.new(:pid => pidfile)
Please sign in to comment.
Something went wrong with that request. Please try again.