diff options
Diffstat (limited to 'lib/unicorn/util.rb')
-rw-r--r-- | lib/unicorn/util.rb | 53 |
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 |