about summary refs log tree commit homepage
path: root/lib/unicorn.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-10-01 13:21:57 -0700
committerEric Wong <normalperson@yhbt.net>2009-10-01 13:21:57 -0700
commiteb619c04765ef31b0e88329cbfd138d24558776e (patch)
tree0c3e8f8c3b5ef9b39c0c164027b5e15e9ba46254 /lib/unicorn.rb
parent9dcbd1387c4c23c84f5a733b6e2e2839b239bdac (diff)
downloadunicorn-eb619c04765ef31b0e88329cbfd138d24558776e.tar.gz
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.
Diffstat (limited to 'lib/unicorn.rb')
-rw-r--r--lib/unicorn.rb16
1 files changed, 11 insertions, 5 deletions
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