diff options
Diffstat (limited to 'lib/logger.rb')
-rw-r--r-- | lib/logger.rb | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/lib/logger.rb b/lib/logger.rb index f24b20b1a6..2eb4e642d2 100644 --- a/lib/logger.rb +++ b/lib/logger.rb @@ -588,24 +588,32 @@ private private def open_logfile(filename) - if (FileTest.exist?(filename)) + begin open(filename, (File::WRONLY | File::APPEND)) - else + rescue Errno::ENOENT create_logfile(filename) end end def create_logfile(filename) - logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT)) - logdev.sync = true - add_log_header(logdev) + begin + logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL)) + logdev.flock(File::LOCK_EX) + logdev.sync = true + add_log_header(logdev) + logdev.flock(File::LOCK_UN) + rescue Errno::EEXIST + # file is created by another process + logdev = open_logfile(filename) + logdev.sync = true + end logdev end def add_log_header(file) file.write( "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName] - ) + ) if file.size == 0 end SiD = 24 * 60 * 60 @@ -614,17 +622,50 @@ private if @shift_age.is_a?(Integer) # Note: always returns false if '0'. if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size) - shift_log_age + lock_shift_log { shift_log_age } end else now = Time.now period_end = previous_period_end(now) if @dev.stat.mtime <= period_end - shift_log_period(period_end) + lock_shift_log { shift_log_period(period_end) } end end end + def lock_shift_log + begin + retry_limit = 8 + retry_sleep = 0.1 + begin + File.open(@filename, File::WRONLY | File::APPEND) do |lock| + lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file + ino = lock.stat.ino + if ino == File.stat(@filename).ino + yield # log shifting + else + # log shifted by another process (i-node before locking and i-node after locking are different) + @dev.close rescue nil + @dev = open_logfile(@filename) + @dev.sync = true + end + end + rescue Errno::ENOENT + # @filename file would not exist right after #rename and before #create_logfile + if retry_limit <= 0 + warn("log rotation inter-process lock failed. #{$!}") + else + sleep retry_sleep + retry_limit -= 1 + retry_sleep *= 2 + retry + end + end + rescue + warn("log rotation inter-process lock failed. #{$!}") + end + end + def shift_log_age (@shift_age-3).downto(0) do |i| if FileTest.exist?("#{@filename}.#{i}") |