about summary refs log tree commit homepage
path: root/lib/unicorn/util.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unicorn/util.rb')
-rw-r--r--lib/unicorn/util.rb53
1 files changed, 41 insertions, 12 deletions
diff --git a/lib/unicorn/util.rb b/lib/unicorn/util.rb
index d2214b7..3951596 100644
--- a/lib/unicorn/util.rb
+++ b/lib/unicorn/util.rb
@@ -1,30 +1,55 @@
+# -*- encoding: binary -*-
+
 require 'fcntl'
 require 'tmpdir'
 
 module Unicorn
+
+  class TmpIO < ::File
+
+    # for easier env["rack.input"] compatibility
+    def size
+      # flush if sync
+      stat.size
+    end
+  end
+
   class Util
     class << self
 
-      APPEND_FLAGS = File::WRONLY | File::APPEND
+      def is_log?(fp)
+        append_flags = File::WRONLY | File::APPEND
+
+        ! fp.closed? &&
+          fp.sync &&
+          fp.path[0] == ?/ &&
+          (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
+      end
 
-      # this reopens logs that have been rotated (using logrotate(8) or
-      # similar).  It is recommended that you install
+      def chown_logs(uid, gid)
+        ObjectSpace.each_object(File) do |fp|
+          is_log?(fp) or next
+          fp.chown(uid, gid)
+        end
+      end
+
+      # This reopens ALL logfiles in the process that have been rotated
+      # using logrotate(8) (without copytruncate) or similar tools.
       # A +File+ object is considered for reopening if it is:
       #   1) opened with the O_APPEND and O_WRONLY flags
       #   2) opened with an absolute path (starts with "/")
       #   3) the current open file handle does not match its original open path
-      #   4) unbuffered (as far as userspace buffering goes)
+      #   4) unbuffered (as far as userspace buffering goes, not O_SYNC)
       # Returns the number of files reopened
       def reopen_logs
         nr = 0
-        ObjectSpace.each_object(File) do |fp|
-          next if fp.closed?
-          next unless (fp.sync && fp.path[0..0] == "/")
-          next unless (fp.fcntl(Fcntl::F_GETFL) & APPEND_FLAGS) == APPEND_FLAGS
 
+        ObjectSpace.each_object(File) do |fp|
+          is_log?(fp) or next
+          orig_st = fp.stat
           begin
-            a, b = fp.stat, File.stat(fp.path)
-            next if a.ino == b.ino && a.dev == b.dev
+            b = File.stat(fp.path)
+            next if orig_st.ino == b.ino && orig_st.dev == b.dev
           rescue Errno::ENOENT
           end
 
@@ -35,6 +60,10 @@ module Unicorn
           end
           fp.reopen(fp.path, open_arg)
           fp.sync = true
+          new_st = fp.stat
+          if orig_st.uid != new_st.uid || orig_st.gid != new_st.gid
+            fp.chown(orig_st.uid, orig_st.gid)
+          end
           nr += 1
         end # each_object
         nr
@@ -45,8 +74,8 @@ module Unicorn
       # buffering is disabled
       def tmpio
         fp = begin
-          File.open("#{Dir::tmpdir}/#{rand}",
-                    File::RDWR|File::CREAT|File::EXCL, 0600)
+          TmpIO.open("#{Dir::tmpdir}/#{rand}",
+                     File::RDWR|File::CREAT|File::EXCL, 0600)
         rescue Errno::EEXIST
           retry
         end