about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-03-02 17:43:28 -0800
committerEric Wong <normalperson@yhbt.net>2009-03-03 11:13:17 -0800
commitdf9f6823188b4189a46b21494d215a07dc6add36 (patch)
tree25e98ab98752007ac9bfff353818dbba2ca756cf
parent72d09ad565e0844a1429fbe8bc83930ed676f737 (diff)
downloadunicorn-df9f6823188b4189a46b21494d215a07dc6add36.tar.gz
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.
-rw-r--r--Manifest1
-rw-r--r--lib/unicorn.rb1
-rw-r--r--lib/unicorn/util.rb40
-rw-r--r--test/exec/test_exec.rb11
4 files changed, 43 insertions, 10 deletions
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