From eb619c04765ef31b0e88329cbfd138d24558776e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 1 Oct 2009 13:21:57 -0700 Subject: Avoid a small window when a pid file can be empty There's always been a small window of opportunity for a script to do File.read(pid).to_i would cause File.read() to read an empty file and return "". This closes that window while hopefully retaining backwards compatibility... We've always checked for dirname(pid) writability in Configurator, so we can safely write to a temporary file in the intended directory and then atomically rename() it to the destination path. --- lib/unicorn.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'lib/unicorn.rb') diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 1d22442..c5a0677 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -182,11 +182,17 @@ module Unicorn end unlink_pid_safe(pid) if pid - # not using O_EXCL here since we may be (intentionally) clobbering an - # existing file. Avoiding /all/ possible race conditions with the pid - # file is hard so we don't unlink it before writing nor do we rename() - # since that's clobbering, too... - File.open(path, 'wb') { |fp| fp.syswrite("#$$\n") } if path + if path + fp = begin + tmp = "#{File.dirname(path)}/#{rand}.#$$" + File.open(tmp, File::RDWR|File::CREAT|File::EXCL, 0644) + rescue Errno::EEXIST + retry + end + fp.syswrite("#$$\n") + File.rename(fp.path, path) + fp.close + end self.set_pid(path) end -- cgit v1.2.3-24-ge0c7