From df9f6823188b4189a46b21494d215a07dc6add36 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 2 Mar 2009 17:43:28 -0800 Subject: Add Unicorn::Util for a reopen_logs method Since I use it myself and also in the tests, we might as well implement it correctly as a class method so people can run it in their trap('USR2') hooks. --- Manifest | 1 + lib/unicorn.rb | 1 + lib/unicorn/util.rb | 40 ++++++++++++++++++++++++++++++++++++++++ test/exec/test_exec.rb | 11 +---------- 4 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 lib/unicorn/util.rb diff --git a/Manifest b/Manifest index 5072d0c..cf6a537 100644 --- a/Manifest +++ b/Manifest @@ -25,6 +25,7 @@ lib/unicorn/const.rb lib/unicorn/http_request.rb lib/unicorn/http_response.rb lib/unicorn/socket.rb +lib/unicorn/util.rb setup.rb test/aggregate.rb test/benchmark/previous.rb diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 90fd29d..6ab42c9 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -5,6 +5,7 @@ require 'unicorn/const' require 'unicorn/http_request' require 'unicorn/http_response' require 'unicorn/configurator' +require 'unicorn/util' # Unicorn module containing all of the classes (include C extensions) for running # a Unicorn web server. It contains a minimalist HTTP server with just enough diff --git a/lib/unicorn/util.rb b/lib/unicorn/util.rb new file mode 100644 index 0000000..0400fd0 --- /dev/null +++ b/lib/unicorn/util.rb @@ -0,0 +1,40 @@ +require 'fcntl' + +module Unicorn + class Util + class << self + + # this reopens logs that have been rotated (using logrotate(8) or + # similar). It is recommended that you install + # 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) + # 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] == "/") + + flags = fp.fcntl(Fcntl::F_GETFL) + open_flags = File::WRONLY | File::APPEND + next unless (flags & open_flags) == open_flags + + begin + a, b = fp.stat, File.stat(fp.path) + next if a.ino == b.ino && a.dev == b.dev + rescue Errno::ENOENT + end + fp.reopen(fp.path, "a") + fp.sync = true + nr += 1 + end # each_object + nr + end + + end + + end +end diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb index 6427453..4f997a3 100644 --- a/test/exec/test_exec.rb +++ b/test/exec/test_exec.rb @@ -56,16 +56,7 @@ end after_fork do |server, worker_nr| trap('USR1') do # log rotation server.logger.info "after_fork: worker=\#{worker_nr} rotating logs..." - ObjectSpace.each_object(File) do |fp| - next if fp.closed? || ! fp.sync - next unless (fp.fcntl(Fcntl::F_GETFL) & File::APPEND) == File::APPEND - begin - fp.stat.ino == File.stat(fp.path).ino - rescue Errno::ENOENT - end - fp.reopen(fp.path, "a") - fp.sync = true - end + Unicorn::Util.reopen_logs server.logger.info "after_fork: worker=\#{worker_nr} done rotating logs" end # trap('USR1') end # after_fork -- cgit v1.2.3-24-ge0c7