class Logger::LogDevice

def lock_shift_log

def lock_shift_log
  retry_limit = 8
  retry_sleep = 0.1
  begin
    File.open(@filename, MODE_TO_OPEN) do |lock|
      lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file
      if File.identical?(@filename, lock) and File.identical?(lock, @dev)
        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)
      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