From 7309e4b73e134ee7969cc8150b6ebaa6b8f8cb62 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 28 Aug 2010 05:30:46 +0000 Subject: make log reopens more robust in multithreaded apps IOError may occur due to race conditions as another thread may close the file immediately after we call File#closed? to check. Errno::EBADF may occur in some applications that close a file descriptor without notifying Ruby (or if two IO objects refer to the same descriptor, possibly one of them using IO#for_fd). (cherry picked from commit 4b23693b9082a84433a9e6c1f358b58420176b27) --- lib/unicorn/util.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/unicorn/util.rb b/lib/unicorn/util.rb index e8c09d0..a735c68 100644 --- a/lib/unicorn/util.rb +++ b/lib/unicorn/util.rb @@ -24,6 +24,8 @@ module Unicorn fp.sync && fp.path[0] == ?/ && (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags + rescue IOError, Errno::EBADF + false end def chown_logs(uid, gid) @@ -46,19 +48,31 @@ module Unicorn ObjectSpace.each_object(File) { |fp| is_log?(fp) and to_reopen << fp } to_reopen.each do |fp| - orig_st = fp.stat + orig_st = begin + fp.stat + rescue IOError, Errno::EBADF + next + end + begin b = File.stat(fp.path) next if orig_st.ino == b.ino && orig_st.dev == b.dev rescue Errno::ENOENT end - File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) } + begin + File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) } + rescue IOError, Errno::EBADF + next + end fp.sync = true new_st = fp.stat + + # this should only happen in the master: 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 -- cgit v1.2.3-24-ge0c7