diff options
author | Eric Wong <normalperson@yhbt.net> | 2010-08-28 05:30:46 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2010-08-28 06:28:04 +0000 |
commit | 4b23693b9082a84433a9e6c1f358b58420176b27 (patch) | |
tree | 180cf66753e78fcb0615b11c62f95aa4abd76863 | |
parent | 096afc1a8e958cc09b4ce8b3bfe76ce056c7ed69 (diff) | |
download | unicorn-4b23693b9082a84433a9e6c1f358b58420176b27.tar.gz |
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).
-rw-r--r-- | lib/unicorn/util.rb | 18 |
1 files 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 |